箭头函数和This

40

我正在尝试使用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。我做错了什么?


http://www.es6fiddle.net/ - thank_you
在这种情况下,“this”是Window。 - Logan Lee
5个回答

52

简短回答: this 指向最近的绑定 this - 在提供的代码中,this 在封闭作用域中找到。

较长回答:箭头函数 完全没有绑定 thisarguments 或其他特殊名称 - 当对象被创建时,在封闭作用域中找到名称 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;

在这两种情况下,对于shout函数,this指向与person定义在同一作用域中的相同作用域,而不是函数添加到person对象时附加到的新作用域。
无法使箭头函数以这种方式工作,但正如@kamituel在他的回答中指出的那样,你可以利用ES6中更短的方法声明模式来获得类似的空间节省。
var person = {
  name: "Jason",
  // ES6 "method" declaration - leave off the ":" and the "function"
  shout() {
    console.log("Hi, my name is", this.name);
  }
};

3
getify的链接已失效,请浏览https://web.archive.org/web/20160625172303/http://blog.getify.com/arrow-this/。 - zowers

33

我同意 @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"

3
点赞了,但请注意this不一定是全局对象。 - Oriol
@Oriol 确认,已经注意到了 - 我假设这是顶层代码。谢谢! - kamituel

18

被接受的回答非常出色、简明清晰,但我想对Sean Vieira所说的稍加解释:

箭头函数根本没有绑定 this arguments 或其他特殊名称。

因为箭头函数没有自己的"this",它使用父级的"this"。 "this" 总是指向父级,而人物对象的父级是 Window(如果你在浏览器中)。

要证明这一点,请在你的控制台中运行以下命令:

var person = {
    name: "Jason",
    anotherKey: this
}
console.log(person.anotherKey)

你将得到Window对象。

我认为这是一种非常有帮助的思考方式。虽然对象字面量中的“this”是另一个讨论,但这并不完全正确。


太棒了 - 我试图理解为什么这种情况发生了这么多次!!! - yehonatan yehezkel
讲解非常清晰。谢谢。 - Alok Ranjan

2

在箭头函数中,this关键字的值由箭头函数定义的位置决定,而不是使用它的位置决定。

因此,如果没有包装在其他命名空间中,this将引用全局/窗口对象。


0

问题在于(MDN)

箭头函数表达式[...]词法绑定了this值。

箭头函数捕获了封闭上下文的this值。

因此,在该函数中,this的值将是您创建对象文字时的this值。在非严格模式下,可能是window,在严格模式下,可能是undefined

要修复它,您应该使用普通函数:

var person = {
  name: "jason",
  shout: function(){ console.log("my name is ", this.name) }
}
person.shout();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接