目录
2. 使用实验性的 public class fields 语法
一、事件处理绑定this
在 JavaScript 中,class的方法默认不会绑定 this
。在传入了 onTouchStart时,若
忘记绑定 this.touchStart
,当你调用touchStart
的时候, this
的值为 undefined
。即事件处理中,未绑定this,无法获取、使用
touchStart(){
console.log('lyl123 this1 = ' + this);//undefined
setTimeout(() => {
console.log('lyl123 this2 = ' + this);//undefined
//this.test();
}, 1000);
}
test(){
console.log('lyl123 test');
}
<div onTouchStart={this.touchStart}/>
React事件处理函数绑定this:构造中使用bind方法,实现方法处用箭头函数、声明处用箭头函数、声明处用bind方法
1. 构造函数中使用bind()方法
constructor(props) {
super(props);
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.touchStart = this.touchStart.bind(this);//给touchStart重新赋值,改变this的指向
}
touchStart(){
console.log('lyl123 this1 = ' + this);
}
<div onTouchStart={this.touchStart}/>
2. 使用实验性的 public class fields 语法
//Create React App 默认启用此语法。
touchStart = ()=>{
console.log('lyl123 this1 = ' + this);
}
<div onTouchStart={this.touchStart}/>
3.es6的箭头函数
class Comp extends React.Component {
touchStart(){
console.log('lyl123 this1 = ' + this);
}
render() {
// 此语法确保 `touchStart` 内的 `this` 已被绑定。
return (<div onTouchStart={()=>{ this.touchStart(); }} /> );
}
}
此语法问题在于每次渲染 Comp组件时都会创建不同的回调函数。如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题。
4.Function.prototype.bind
touchStart(){
console.log('lyl123 this1 = ' + this);
}
<div onTouchStart={this.touchStart.bind(this)}/>
Function.prototype.bind和使用箭头函数是等价的,实际上每次组件渲染时都生成了新的回调函数。
方式3/4的使用场景:需要传递额外参数时使用。
在循环中,通常我们会为事件处理函数传递额外的参数。例如,若 id
是你要删除那一行的 ID,以下两种方式都可以向事件处理函数传递参数:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
在这两种情况下,React 的事件对象 e
会被作为第二个参数传递。如果通过箭头函数的方式,事件对象必须显式的进行传递,而通过 bind
的方式,事件对象以及更多的参数将会被隐式的进行传递。
参考:
Understanding JavaScript Bind ()
二、JS中的this
this 永远指向最后调用它的那个对象
虽然obj.foo和foo指向同一个函数,但是执行结果可能不一样。请看下面的例子。
var obj = {
foo: function () { console.log(this.bar) },
bar: 1
};
var foo = obj.foo;
var bar = 2;
obj.foo() // 1
foo() // 2
this指的是函数运行时所在的环境。对于obj.foo()来说,foo运行在obj环境,所以this指向obj;对于foo()来说,foo运行在全局环境,所以this指向全局环境。所以,两者的运行结果不一样。
this的设计目的就是在函数体内部,指代函数当前的运行环境。
var f = function () {
console.log(x);
};
var f = function () {
console.log(this.x);
}
上面代码中,函数体里面的this.x就是指当前运行环境的x。
bind 是创建一个新的函数,我们必须要手动去调用
b.bind(a,1,2)()
箭头函数的 this 始终指向函数定义时的 this,而非执行时。
箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this 为 undefined
// onTouchStart={this.touchStart}
onTouchStart={()=>{
// this.touchStart.bind(this);
this.touchStart();
}}