javascript - 对于一组实例,对于每个实例,如何通过该方法的名称调用某个方法?
问题描述
我正在尝试将粒子类的函数 behappy() 作为 ParticleSystem 类的 applyBehavior 函数的参数传递。我错过了一些语法吗?我不明白我的电话有什么问题。
最小的可重现代码在这里和这里。
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");
预期输出应该是:
“我现在很开心” “我现在很开心” “我现在很开心” “我现在很开心” “我现在很开心” “我现在很开心” “我现在很开心” “我现在很开心” “我现在很开心”我现在很开心” “我现在很开心”
解决方案
如果粒子系统applyBehavior
应该调用粒子的方法,首先应该将此方法重命名为callBehavior
,executeBehavior
或者更好,executeParticles
其次需要提供粒子的方法/行为名称作为第一个参数而不是函数引用。
编辑
正如Bergi已经指出的那样,其中一个原因必须假设实例的任何方法Particle
最有可能在Particle
实例的this
上下文中运行。
AParticleSystem
的executeParticles
方法必须以一种为任何可访问的方法显式提供这样一个上下文的方式来实现Particle
。由于函数本身就是对象,因此它们带有两种方法可以完全实现...call
和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; }
推荐阅读
- android - 像whats app一样将edittext高度增加到5行
- sql - 基于日期的动态列名
- ios - iOS CocoaLumberjack:如果启用了 backgroundModes 并且应用程序在模拟器中运行,则每次启动应用程序时都会创建新的日志文件
- angular - Angular 模块在运行时动态导入捆绑在 s3 上的另一个 Angular 模块
- python - 我正在尝试进行日志测试,并且我已经进行了输出,但是我有一些要添加的东西,但是我做不到
- c# - C# 中代码的哪一部分出现“内存不足异常”错误?还有其他替代方式吗?
- database - 如何通过查询在 SQLite 中找到数据的来源?
- c++ - 填充动态数组时获取退出状态-1
- mysql - 从同一列获取信息并将其显示在多个列上
- javascript - 如何在nodejs中将多个图像添加到单个tiff?