Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在react中使用箭头函数引发的对this的思考 #14

Open
youngwind opened this issue Dec 27, 2015 · 6 comments
Open

在react中使用箭头函数引发的对this的思考 #14

youngwind opened this issue Dec 27, 2015 · 6 comments
Labels

Comments

@youngwind
Copy link
Owner

前言

用es6一段时间了,某次想把组件内部的函数都改写成箭头函数。比如

render : function(){
  console.log(this.props);
}

改写成下面这样的

render () => {
  console.log(this.props);  // 报错,this是undefined
}

结果显示this是undefined,我就感觉箭头函数的this有坑,研究了一番,发现还真的不一样。

箭头函数this指向与普通函数不同

箭头函数的this指向函数定义时的作用域,普通函数的this指向函数调用时的作用域。
因为箭头函数没有自己的上下文。
完整地例子参考这里:https://jsbin.com/vetecagupa/edit?js,console
注:在非严格模式执行

这个例子会输出1,因为普通函数的this指向函数被调用时候的作用域,也就是demo

var x = 10;
var demo = {
    x : 1,
    test1 : function() { console.log(this.x); },
    test2 : function() {
        this.test1();
    }
};

demo.test2();  // 1  

这个例子会输出10,因为test1函数在定义的时候处于global作用域,调用的时候this维持不变。

var x = 10;
var demo2 = {
    x : 1,
    test1 : () => { console.log(this.x); },
    test2 : function() {
        this.test1();
    }
};

demo2.test2();  // 10

这个例子会报错,因为函数test2定义的时候处于global作用域,所以调用的时候this指向global,而global中不存在test2方法。

var x = 10;
var demo3 = {
    x : 1,
    test1 : () => { console.log(this.x); },
    test2 : () =>{
        this.test1();
    }
};

demo3.test2();  // error: this.test1 is not a function

回到render函数

搞清楚了箭头函数的this问题,但是由于我还没搞清楚react定义组件的时候作用域的问题,所以暂时没办法搞明白如何在组件中使用箭头函数,以后有时间再研究研究,未完待续。。。。

@cagen
Copy link

cagen commented Jan 12, 2016

可能的三种方案

  1. ES7 Property Initializers (Babel Stage 0提供):

    Class MyComponent extends React.Component {
      render = () => {
        console.log(this.props);
      }
    }
  2. Autobind Decorator:

    import autobind from 'autobind-decorator';
    
    Class MyComponent extends React.Component {
      @autobind
      render () {
        console.log(this.props);
      }
    }
  3. 构造函数里头手动绑定:

    Class MyComponent extends React.Component {
      constructor() {
        this.render = this.render.bind(this);
      }
      render() {
        console.log(this.props);
      }
    }

@youngwind
Copy link
Owner Author

@cagen thanks!

@ryanzhouff
Copy link

@youngwind 谢谢你提出的问题
@cagen 谢谢你的回答
也可以通过安装babel-plugin-transform-class-properties插件解决这个问题

class Header extends React.Component {
    handleClick = (e) => {
        console.log(e);
    }
    render() {
        return (
            <div>
                    <button type="button" onClick={this.handleClick}>点击</button>
            </div>
        )
    }
}

具体使用方法,可以到Babel官网查看

@kangenpingmai
Copy link

var demo2 = {
x : 1,
test1 : () => { console.log(this.x); },
test2 : function() {
this.test1();
}
};
这个test1怎么是定义在全局的,这不是再demo2里面定义的吗

@RuinousCheng
Copy link

var demo2 = {
x : 1,
test1 : () => { console.log(this.x); },
test2 : function() {
this.test1();
}
};
这个test1怎么是定义在全局的,这不是再demo2里面定义的吗

test1 依然是demo2的属性,但是调用时箭头函数里的this指向的是全局对象。

@sanfengliao
Copy link

sanfengliao commented Sep 28, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants