对于一组实例,一个实例如何通过该方法的名称调用某个方法?
For an array of instances, how does one, for each instance, invoke a certain method by this method's name?
我正在尝试传递 Particle Class 的函数 behappy(),作为 ParticleSystem class 的 applyBehavior 函数的参数。我缺少一些语法吗?我不明白我的电话有什么问题。
最小可重现代码在这里 here。
class ParticleSystem{
constructor(){
this.particles = [];
this.numberOfParticles = 10;
for(let i = 0; i < this.numberOfParticles; i++){
this.particles.push(new Particle());
}
}
applyBehavior(behavior, message){
for(let i = 0; i < this.numberOfParticles; i++){
this.particles[i].behavior(message);
}
}
}
class Particle{
constructor(){}
behappy(message){
print(message);
}
}
let particlesys = new ParticleSystem();
particlesys.applyBehavior(behappy, "i am happy now");
预期输出应该是:
"i am happy now" "i am happy now" "i am happy now" "i am happy now" "i
am happy now" "i am happy now" "i am happy now" "i am happy now" "i am
happy now" "i am happy now"
如果粒子系统的 applyBehavior
应该调用粒子的方法,首先应该将此方法重命名为 callBehavior
、executeBehavior
或者更好的是 executeParticles
其次需要提供粒子的 method/behavior 名称 作为第一个参数而不是函数引用。
编辑
正如 Bergi 已经指出的那样,原因之一必须假设 Particle
实例的任何方法最有可能在 Particle
实例的this
上下文。
A ParticleSystem
的 executeParticles
方法必须以明确为任何可访问的 Particle
方法提供此类上下文的方式实现。由于函数本身就是对象,因此它们带有两种方法来实现这一点...... call
and apply
。可以为这两种方法提供目标对象。此目标对象确实成为通过 call
/apply
.
调用的任何 method/function 的上下文
示例代码进行了相应更改,以显示此用例...
class ParticleSystem{
constructor(){
this.particles = [];
this.numberOfParticles = 10;
for(let i = 0; i < this.numberOfParticles; i++){
this.particles.push(new Particle(i));
}
}
executeParticles(behaviorName, message){
// for(let i = 0; i < this.numberOfParticles; i++){
// this.particles[i][behaviorName](message);
// }
this.particles.forEach(particle => {
const behavior = particle && particle[behaviorName];
if (typeof behavior === 'function') {
// MDN: "Function.prototype.call"
// see: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call]
behavior.call(particle, message);
}
});
}
}
class Particle{
constructor(idx){
this.id = `particle_${ idx }`;
}
behappy(message){
console.log(`${ this.id } logs ... "${ message }"`);
}
}
let particlesys = new ParticleSystem();
particlesys.executeParticles('behappy', "I'am happy now.");
.as-console-wrapper { min-height: 100%!important; top: 0; }
最通用的 executeParticles
实现不对粒子方法的参数做任何假设,将利用 apply
...
class ParticleSystem{
constructor(){
this.particles = [];
this.numberOfParticles = 10;
for(let i = 0; i < this.numberOfParticles; i++){
this.particles.push(new Particle(i));
}
}
executeParticles(behaviorName, ...args){
this.particles.forEach(particle => {
const behavior = particle && particle[behaviorName];
if (typeof behavior === 'function') {
behavior.apply(particle, args);
}
});
}
}
class Particle{
constructor(idx){
this.id = `particle_${ idx }`;
}
behappy(message){
console.log(`${ this.id } logs ... "${ message }"`);
}
}
let particlesys = new ParticleSystem();
particlesys.executeParticles('behappy', "I'am happy now.");
.as-console-wrapper { min-height: 100%!important; top: 0; }
我正在尝试传递 Particle Class 的函数 behappy(),作为 ParticleSystem class 的 applyBehavior 函数的参数。我缺少一些语法吗?我不明白我的电话有什么问题。
最小可重现代码在这里 here。
class ParticleSystem{
constructor(){
this.particles = [];
this.numberOfParticles = 10;
for(let i = 0; i < this.numberOfParticles; i++){
this.particles.push(new Particle());
}
}
applyBehavior(behavior, message){
for(let i = 0; i < this.numberOfParticles; i++){
this.particles[i].behavior(message);
}
}
}
class Particle{
constructor(){}
behappy(message){
print(message);
}
}
let particlesys = new ParticleSystem();
particlesys.applyBehavior(behappy, "i am happy now");
预期输出应该是:
"i am happy now" "i am happy now" "i am happy now" "i am happy now" "i am happy now" "i am happy now" "i am happy now" "i am happy now" "i am happy now" "i am happy now"
如果粒子系统的 applyBehavior
应该调用粒子的方法,首先应该将此方法重命名为 callBehavior
、executeBehavior
或者更好的是 executeParticles
其次需要提供粒子的 method/behavior 名称 作为第一个参数而不是函数引用。
编辑
正如 Bergi 已经指出的那样,原因之一必须假设 Particle
实例的任何方法最有可能在 Particle
实例的this
上下文。
A ParticleSystem
的 executeParticles
方法必须以明确为任何可访问的 Particle
方法提供此类上下文的方式实现。由于函数本身就是对象,因此它们带有两种方法来实现这一点...... call
and apply
。可以为这两种方法提供目标对象。此目标对象确实成为通过 call
/apply
.
示例代码进行了相应更改,以显示此用例...
class ParticleSystem{
constructor(){
this.particles = [];
this.numberOfParticles = 10;
for(let i = 0; i < this.numberOfParticles; i++){
this.particles.push(new Particle(i));
}
}
executeParticles(behaviorName, message){
// for(let i = 0; i < this.numberOfParticles; i++){
// this.particles[i][behaviorName](message);
// }
this.particles.forEach(particle => {
const behavior = particle && particle[behaviorName];
if (typeof behavior === 'function') {
// MDN: "Function.prototype.call"
// see: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call]
behavior.call(particle, message);
}
});
}
}
class Particle{
constructor(idx){
this.id = `particle_${ idx }`;
}
behappy(message){
console.log(`${ this.id } logs ... "${ message }"`);
}
}
let particlesys = new ParticleSystem();
particlesys.executeParticles('behappy', "I'am happy now.");
.as-console-wrapper { min-height: 100%!important; top: 0; }
最通用的 executeParticles
实现不对粒子方法的参数做任何假设,将利用 apply
...
class ParticleSystem{
constructor(){
this.particles = [];
this.numberOfParticles = 10;
for(let i = 0; i < this.numberOfParticles; i++){
this.particles.push(new Particle(i));
}
}
executeParticles(behaviorName, ...args){
this.particles.forEach(particle => {
const behavior = particle && particle[behaviorName];
if (typeof behavior === 'function') {
behavior.apply(particle, args);
}
});
}
}
class Particle{
constructor(idx){
this.id = `particle_${ idx }`;
}
behappy(message){
console.log(`${ this.id } logs ... "${ message }"`);
}
}
let particlesys = new ParticleSystem();
particlesys.executeParticles('behappy', "I'am happy now.");
.as-console-wrapper { min-height: 100%!important; top: 0; }