在react中使用箭头函数引发的对this的思考
youngwind opened this issue · 6 comments
前言
用es6一段时间了,某次想把组件内部的函数都改写成箭头函数。比如
render : function(){
console.log(this.props);
}
改写成下面这样的
render () => {
console.log(this.props); // 报错,this是undefined
}
结果显示this是undefined,我就感觉箭头函数的this有坑,研究了一番,发现还真的不一样。
箭头函数this指向与普通函数不同
箭头函数的this指向函数定义时的作用域,普通函数的this指向函数调用时的作用域。
因为箭头函数没有自己的上下文。
完整地例子参考这里:http://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定义组件的时候作用域的问题,所以暂时没办法搞明白如何在组件中使用箭头函数,以后有时间再研究研究,未完待续。。。。
可能的三种方案
-
ES7 Property Initializers (Babel Stage 0提供):
Class MyComponent extends React.Component { render = () => { console.log(this.props); } }
-
import autobind from 'autobind-decorator'; Class MyComponent extends React.Component { @autobind render () { console.log(this.props); } }
-
构造函数里头手动绑定:
Class MyComponent extends React.Component { constructor() { this.render = this.render.bind(this); } render() { console.log(this.props); } }
@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官网查看
var demo2 = {
x : 1,
test1 : () => { console.log(this.x); },
test2 : function() {
this.test1();
}
};
这个test1怎么是定义在全局的,这不是再demo2里面定义的吗
var demo2 = {
x : 1,
test1 : () => { console.log(this.x); },
test2 : function() {
this.test1();
}
};
这个test1怎么是定义在全局的,这不是再demo2里面定义的吗
test1 依然是demo2的属性,但是调用时箭头函数里的this指向的是全局对象。