改成:
this.colors.forEach((x) => this.printColor(x));
原始代码无法按预期工作的原因与 scope 在 javascript 中的工作方式有关,特别是 this 的值是如何绑定的。
要了解的主要内容是(通常)当您调用一个函数时,this 被设置为调用该方法的对象。
wookie.eatBanana(); // inside the eatBanana method, this === wookie
但是,如果您将方法与对象分开调用,this 最终会成为 undefined:
const detachedFn = wookie.eatBanana;
// same function, but now this === undefined
detachedFn();
当你将this.printColor 传递给forEach 时,你正在做的是传递函数本身,它最终会被调用而不绑定到你的对象:
const detachedFn = this.printColor;
this.colors.forEach((x) => detachedFn(x)); // this === undefined inside detachedFn, because it's invoked standalone
在forEach 实现中,它只是调用它所提供的函数。有效:
// pseudocode
function forEach(fn) {
fn(); // no reference to your class instance; fn is just a regular function.
}
定义一个调用 this.printColor() 的新函数会保留作用域:
this.colors.forEach((x) => this.printColor(x));
function forEach(fn) {
fn(); // inside this function your method is called *on your object*, preserving the 'this' binding.
}
箭头函数auto-bind to the parent scope:
箭头函数没有自己的 this。使用封闭词法范围的 this 值;箭头函数遵循正常的变量查找规则。因此,在搜索当前作用域中不存在的 this 时,箭头函数最终会从其封闭作用域中找到 this。
如果您将方法声明为箭头函数,箭头函数自动绑定也可以方便地解决这些问题。 (这是实验性的,可能需要 babel class properties plugin)。
// declaring this method as an arrow function causes it to bind to
// the parent scope (the class instance) which means you can invoke
// it independently of the instance.
printColor = (colorObj) => {
console.log(this.sourceFile, colorObj.name, colorObj.hex);
}
// now this is fine because printColor is already bound to 'this'
this.colors.forEach(this.printColor);
或者,作为 palaѕн pointed out,显式调用 bind:
// make a copy of printColor that's explicitly bound to 'this'.
const explicitlyBoundFn = this.printColor.bind(this);
// works
this.colors.forEach(explicitlyBoundFn);
您也可以通过call 或apply 完成此操作,它们都允许您传入一个范围(尽管在这种情况下没有理由这样做)。
// no reason to do this, but it works.
const detachedFn = this.printColor;
this.colors.forEach((x) => detachedFn.call(this, x));
希望这会有所帮助。如果有任何需要澄清的地方,很高兴更新它。