[reactjs]匿名函数定义不等同

时间:2017-02-01 21:34:16

标签: reactjs

我是React的新手。我在遵循React官方页面https://facebook.github.io/react/docs/state-and-lifecycle.html的“快速入门”时遇到了一个奇怪的问题。您可以在此处尝试使用CodePen:http://codepen.io/gaearon/pen/amqdNA?editors=0010

在此代码段中

componentDidMount() {
    this.timerID = setInterval(
        () => this.tick(),
        1000
    );
}

它使用箭头函数语法定义一个将重复执行的函数,方法是将匿名函数对象作为setInterval()的第一个参数传递。

由于我是一个好奇的家伙,我尝试了几种不同的方法来传递“等效”函数对象作为第一个参数。但是我的方式都没有用。

componentDidMount() {
    this.timerID = setInterval(
        this.tick, // This cannot work in CodePen

        //function () {
            //this.tick();
        //}, // No

        //function () {
            //return this.tick();
        //}, // No

        //() => this.tick(), // This is the official way that works
        //() => {this.tick();}, // This also works, but notice the difference between this and the last one 
        //() => {this.tick()}, // Also works
        //() => {return this.tick();}, // Also works, think it equivalent as official one
        1000
    );
}

我认为在纯Javascript代码段中,所有这些方式都适用于setInterval。特别是,正如官方文档(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions)所说,箭头函数定义通常等同于function () { ... }定义。但它们似乎在React和Babel中并不相同。

在我通过Babel检查编译的Javascript代码后,它们因_this2对象而不同。

// Javascript compiled by Babel
Clock.prototype.componentDidMount = function componentDidMount() {
    var _this2 = this;

    this.timerID = setInterval(
        //this.tick // This is the compiled code using one of my way

        /*function () {
            this.tick();
        },*/ // This is another one

        function () {
            return _this2.tick();
        }, // This is the compiled code using the official way

        //function () {
            //_this2.tick();
        //}, // This is the compiled code of another working example
        1000
    );
};

所以,我问,为什么我们必须在这里使用箭头函数语法?为什么等效方法无法正确编译?这是React还是Babel的错误?

编辑:

行。非常感谢你们! Javascript 几乎中关于“this”的那个棘手的事情回答了我的每一个问题。现在我知道() => {}定义和function () {}定义之间存在很大差异,为什么Babel没有按照我的预期行事。

但是,这并没有回答为什么这不起作用

this.timerID = setInterval(
    this.tick, // This cannot work in CodePen
    1000
);

有人也可以看看这个“简单”的代码行吗?我想这与“这个”的方式无关吗?

1 个答案:

答案 0 :(得分:1)

函数(){}和()=> {} NOT 是同一件事。

考虑一下:

#1
function foo() { 
  console.log('foo');
}

vs:
#2
foo = () => { 
  console.log('foo')
}

函数#1将新创建的上下文限制在函数中,而函数#2不创建新的上下文this变量。

当Babel转换所有东西时,我相信为了让函数#2没有新的上下文它会做这样的事情:

foo = () => {
  console.log(this.data);
}

<强>变为

var this_2 = this;
function foo () {
  console.log(this_2.data);
}