在JavaScript中,以下两种写法是不等价的:
let obj = {
tmp:'Yes!',
testLog:function(){
console.log(this.tmp);
}
};
obj.testLog(); //方法一:此时为obj调用testLog函数,其中的this指向obj,所以结果为Yes
let tmpLog = obj.testLog; //方法二
tmpLog(); //此时为window调用tmpLog函数,其中this指向window,但window没有定义tmp,所以结果为undefined
bind 方法确保了第二种写法与第一种写法相同。
看了好多博客都说是this丢失了指向,虽然可以这么理解。
但究其原因,我觉得只是因为在不同作用域里调用了同一个函数。而函数里面的this,由于指向不同外部环境从而产生了问题,this指向没丢,指的方向不同罢了。
bind() 方法创建一个新的函数,在 bind() 被调用时,该新函数的 this 指向 bind() 中的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
简单理解,当render里如果出现一个onClick={this.incrementAsync}
此时的步骤其实是
let incrementAsync = this.incrementAsync
onClick={ incrementAsync }
如果没有bind(this)将指向绑定到当前组件,此时的this.incrementAsync
等于window.incrementAsync
,而window里没有声明incrementAsync,所以会导致其值为undefined
import React, { Component } from 'react'
class Counter extends Component {
constructor(props) {
super(props);
this.incrementAsync = this.incrementAsync.bind(this); //bind()返回拥有指定this的原函数的拷贝,然后初始化赋值给左端
}
incrementAsync() {
setTimeout(this.props.onIncrement, 1000)
}
render() {
return (
<p>
<button onClick={this.incrementAsync}> //如果没有constructor里的bind,该this指向window
Increment async
</button>
</p>
)
}
}
如果你不喜欢在构造函数里用bind,那么你可以在回调中使用一个箭头函数:
import React, { Component } from 'react'
incrementAsync() {
setTimeout(this.props.onIncrement, 1000)
}
render() {
return (
<p>
<button onClick={ (e) => this.incrementAsync(e) }>
Increment async
</button>
</p>
)
}
}
这个语法的问题是,每次 LoggingButton 渲染时都创建一个不同的回调。在多数情况下,没什么问题。然而,如果这个回调被作为 prop(属性) 传递给下级组件,这些组件可能需要额外的重复渲染。我们通常建议在构造函数中进行绑定,以避免这类性能问题。
网友评论