我正在尝试使用ES6,并想在我的函数内包含一个属性,如下所示:
var person = {
name: "jason",
shout: () => console.log("my name is ", this.name)
}
person.shout() // Should print out my name is jason
然而,当我运行此代码时,控制台仅记录my name is
。我做错了什么?
我正在尝试使用ES6,并想在我的函数内包含一个属性,如下所示:
var person = {
name: "jason",
shout: () => console.log("my name is ", this.name)
}
person.shout() // Should print out my name is jason
然而,当我运行此代码时,控制台仅记录my name is
。我做错了什么?
简短回答: this
指向最近的绑定 this
- 在提供的代码中,this
在封闭作用域中找到。
较长回答:箭头函数 完全没有绑定 this
、arguments
或其他特殊名称 - 当对象被创建时,在封闭作用域中找到名称 this
,而不是 person
对象。通过移动声明可以更清楚地看到这一点:
var person = {
name: "Jason"
};
person.shout = () => console.log("Hi, my name is", this);
当使用ES5中箭头语法的模糊近似翻译时,甚至更加清晰:
var person = {
name: "Jason"
};
var shout = function() {
console.log("Hi, my name is", this.name);
}.bind(this);
person.shout = shout;
this
指向与person
定义在同一作用域中的相同作用域,而不是函数添加到person
对象时附加到的新作用域。var person = {
name: "Jason",
// ES6 "method" declaration - leave off the ":" and the "function"
shout() {
console.log("Hi, my name is", this.name);
}
};
我同意 @Sean Vieira 的看法 - 在这种情况下,this
绑定到全局对象(或者,如评论中指出的那样,更一般地绑定到包含的范围)。
如果你想要一个更短的语法,还有另一种选择 - 增强的对象字面量支持属性函数的短语法。在那里,this
将会按照你的期望进行绑定。请参见 shout3()
:
window.name = "global";
var person = {
name: "jason",
shout: function () {
console.log("my name is ", this.name);
},
shout2: () => {
console.log("my name is ", this.name);
},
// Shorter syntax
shout3() {
console.log("my name is ", this.name);
}
};
person.shout(); // "jason"
person.shout2(); // "global"
person.shout3(); // "jason"
this
不一定是全局对象。 - Oriol被接受的回答非常出色、简明清晰,但我想对Sean Vieira所说的稍加解释:
箭头函数根本没有绑定 this arguments 或其他特殊名称。
因为箭头函数没有自己的"this",它使用父级的"this"。 "this" 总是指向父级,而人物对象的父级是 Window(如果你在浏览器中)。
要证明这一点,请在你的控制台中运行以下命令:
var person = {
name: "Jason",
anotherKey: this
}
console.log(person.anotherKey)
你将得到Window对象。
我认为这是一种非常有帮助的思考方式。虽然对象字面量中的“this”是另一个讨论,但这并不完全正确。
在箭头函数中,this
关键字的值由箭头函数定义的位置决定,而不是使用它的位置决定。
因此,如果没有包装在其他命名空间中,this
将引用全局/窗口对象。
问题在于(MDN)
箭头函数表达式[...]词法绑定了this值。
箭头函数捕获了封闭上下文的this值。
因此,在该函数中,this
的值将是您创建对象文字时的this
值。在非严格模式下,可能是window
,在严格模式下,可能是undefined
。
要修复它,您应该使用普通函数:
var person = {
name: "jason",
shout: function(){ console.log("my name is ", this.name) }
}
person.shout();