简体   繁体   English

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

[英][reactjs]Anonymous function definitions not equivalent

I am new to React. 我是React的新手。 I encountered a strange problem while I am following the "Quick Start" of React official page https://facebook.github.io/react/docs/state-and-lifecycle.html . 我在遵循React官方页面的“快速入门” https://facebook.github.io/react/docs/state-and-lifecycle.html时遇到了一个奇怪的问题。 You can try on CodePen here: http://codepen.io/gaearon/pen/amqdNA?editors=0010 您可以在此处尝试使用CodePen: http ://codepen.io/gaearon/pen/amqdNA?editors=0010

In this code snippet 在此代码段中

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

it uses arrow function syntax to define a function which would be executed repeatedly, by passing the anonymous function object as the first argument of setInterval() . 通过使用匿名函数对象作为setInterval()的第一个参数,它使用箭头函数语法定义了可以重复执行的函数。

Since I am a curious guy, I tried several different ways to pass an "equivalent" function object as the first argument. 因为我是一个好奇的人,所以我尝试了几种不同的方法将“等效”功能对象作为第一个参数传递。 But none of my ways works. 但是我的方法都不行。

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
    );
}

I think in a pure Javascript code snippet, all these ways are valid for setInterval to work. 我认为在纯Javascript代码段中,所有这些方法对于setInterval都是有效的。 Especially, as the official document ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions ) says, the arrow function definition is generally equivalent to the function () { ... } definition. 特别是,如官方文档( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions )所述,箭头函数定义通常等效于function () { ... }定义。 But they just seem not equivalent in React and Babel. 但是它们在React和Babel中似乎并不等效。

After I examined the compiled Javascript code by Babel, they differ by a _this2 object. 在我检查了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
    );
};

So, I am asking, why must we use the arrow function syntax here? 所以,我问,为什么我们必须在这里使用箭头函数语法? Why the equivalent ways does not get compiled correctly? 为什么等效方法无法正确编译? Is this a bug of React or Babel? 这是React还是Babel的错误?

EDIT: 编辑:

OK. 好。 Thank you very much, guys! 非常感谢你们! That tricky thing about "this" in Javascript almost answers every question I have. Javascript中关于“ this”的棘手问题几乎可以回答我的每个问题。 Now I know there is a big difference between () => {} definition and function () {} definition, and why Babel doesn't do what I expect. 现在,我知道() => {}定义和function () {}定义之间有很大的区别,以及为什么Babel不按照我的期望做。

But, this does not answer why this could not work 但是,这不能回答为什么这行不通

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

Could someone also take a look on this "easy" line of code? 有人还能看看这行“简单”的代码吗? I guess it's not related to "this" in the same way? 我猜它与“ this”不一样吗?

Function () {} and () =>{} are NOT the same thing. 函数(){}和()=> {}是一样的东西。

Consider: 考虑:

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

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

Function #1 has a newly created context confined to the function, whereas function #2 doesn't create a new context this variable. 函数1具有一个新创建的上下文,该上下文仅限于该函数,而函数2没有this变量创建新的上下文。

When Babel converts everything, I believe in order for function #2 to not have a new context it does something like this: 当Babel转换所有内容时,我相信为了让函数#2没有新的上下文,它会执行以下操作:

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

Becomes 成为

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM