提问人:Luis Aguiar 提问时间:8/4/2021 更新时间:8/4/2021 访问量:53
javascript:这个 != 窗口,属性仍未定义
javascript: this != window, properties still undefined
问:
我正在做一个关于Javascript的Salesforce跟踪,出现了一个关于这个范围的问题。
我以为this.hello在函数中是未定义的,因为这将指向窗口,其中.name down不存在。但是 window == 这是 false,该对象的日志显示它访问了属性。
那么,为什么 this.name 是未定义的呢?
let message = {
hello: "Hello",
names: ["Sue", "Joe"],
showMessage: function () {
console.log("this, message");
console.log(window == this);
console.log(this);
this.names.forEach(function (name) {
console.log(this.hello + " " + name);
});
}
};
message.showMessage();
/*
false
Object
hello: "Hello"
names: (2) ["Sue", "Joe"]
Sue
"undefined Sue"
"undefined Joe"
*/
返回:
答:
如果在 forEach 中使用箭头函数,将获得预期结果:
let message = {
hello: "Hello",
names: ["Sue", "Joe"],
showMessage: function () {
console.log("this, message");
console.log(window == this);
console.log(this);
this.names.forEach((name) => {
console.log(this.hello + " " + name);
});
}
};
message.showMessage();
这是因为箭头函数没有自己的绑定,而是从周围的作用域获取它。您的函数未绑定到任何对象,因此它采用 .this
window
this
这是因为关键字获取了您调用的函数的上下文。所以它不等于窗口。this
let message = {
hello: "Hello",
names: ["Sue", "Joe"],
showMessage: function () {
console.log(this);
}
};
message.showMessage();
您可以看到,这是引用对象的,因为它是方法的上下文。message
showMessage
在下面的示例中,您可以看到它被引用到窗口,因为它位于另一个函数中,没有任何先前的引用,因此它从窗口获取:this
this
let message = {
hello: "Hello",
names: ["Sue", "Joe"],
showMessage: function () {
this.names.forEach(function (name) {
console.log(this === window); // referred to the window
});
}
};
message.showMessage();
为了避免这种情况,只需使用箭头函数:
let message = {
hello: "Hello",
names: ["Sue", "Joe"],
showMessage: function () {
this.names.forEach((name) => { // arrow function
console.log(this.hello + " " + name); // referred to the object
});
}
};
message.showMessage();
评论
让我们回过头来:除非你已经是 JS 专家,否则如果你想要基于面向对象编程的一般知识,以你期望的方式工作的“对象方法和属性”,请不要使用对象文字。
使用类:
class Message {
constructor(hello = ``, names = []) {
this.hello = hello;
this.names = names.slice();
}
showMessage() {
this.names.forEach(name => console.log(`${this.hello} ${name}`));
}
}
let message = new Message(`hello`, [`Sue`, `Joe`]);
message.showMessage();
因为如果你想坚持对象文字,你最好在深层次上理解它在
JavaScript 中是如何工作的。
另请注意,所有字符串都使用反引号:不要使用或在现代 JS 中使用模板字符串表示法,直到您知道何时不应该使用它们(这几乎永远不会)。'
"
乍一看,我的脑袋说“哦,这是因为它将范围绑定到新功能”,但当我仔细想想时,这就没有意义了。
console.log(window == this);
console.log(this);
“this”绑定到“message”的对象范围,而不是函数。因此,声明对该范围没有影响。您还可以在其中看到,其中显示了正在记录的整个对象。showMessage: function ()
console.log(this)
那么下一个问题就可以了,但是为什么下一个功能,突然实际上改变了作用域。我认为这是因为它与函数无关,很可能是因为使用 forEach 创建了一个新范围而不是函数。因此,在该循环中使用的 this 绑定到循环,而不是函数。function (name)
无论是那个还是其他正在发生的事情,都更奇怪,比如 javascript 如果函数作用域被分配给一个对象,则忽略函数作用域,但如果它是另一个函数中的函数,则实现函数作用域。第一种选择对我来说听起来更合理。
但我只是一个投机的白痴。
评论
此
范围的工作原理。this
function() {}
this
forEach
function
this
this
window