gpt4 book ai didi

javascript - 无法读取未定义的属性,运行时错误

转载 作者:行者123 更新时间:2023-11-30 23:58:19 24 4
gpt4 key购买 nike

我这里有以下代码:

class ColorPrinter {
constructor(sourceFile, colors) {
this.sourceFile = sourceFile
this.colors = colors
}

showColors() {
this.colors.forEach(this.printColor);
}

printColor(colorObj) {
console.log(this.sourceFile, colorObj.name, colorObj.hex);
}
}


const colors = [{name: "red", hex: "#FF0000"}, {name: "yellow", hex: "#FFFF00"}, {name: "cyan", hex: "#0000FF"}];
const cp = new ColorPrinter('colors.csv', colors);
cp.showColors();

但是,当我运行它时,我收到运行时错误:

"TypeError: Cannot read property 'sourceFile' of undefined"

我不明白JS为什么不高兴。我不想从文件中读取,但它不会将字符串作为参数。

最佳答案

将其更改为:

this.colors.forEach((x) => this.printColor(x));

您的原始代码无法按预期工作的原因与 scope 在 javascript 中的工作方式有关,特别是 this 的值如何绑定(bind)。

要理解的主要事情是,(通常)当您调用函数时,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 时,您所做的就是传递函数本身,最终会在没有绑定(bind)到您的对象:

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 :

An arrow function does not have its own this. The this value of the enclosing lexical scope is used; arrow functions follow the normal variable lookup rules. So while searching for this which is not present in current scope, an arrow function ends up finding the this from its enclosing scope.

如果您首先将方法声明为箭头函数,那么箭头函数自动绑定(bind)也可以方便地解决这些问题。 (这是实验性的,可能需要 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));

希望这有帮助。如果有任何需要澄清的地方,很乐意更新。

关于javascript - 无法读取未定义的属性,运行时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60910526/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com