函数中使用this
在函数中使用this的时候,我们经常用箭头函数声明。或者使用bind来修改this的指向。但是这究竟是为什么呢?
下面我们来看看直接在函数中直接使用会出现什么问题吧
在函数中直接使用this的问题
import React, { Component } from 'react';
export default class App extends Component {
state= {
name: '张三'
}
handleClick (){
console.log(this);
this.setState({name:'李四'})
}
render() {
return (
<div>
<h1>我的名字是{this.state.name}</h1>
<button onClick={this.handleClick}>点击我改名字</button>
</div>
);
}
}
很简单的例子,一个name状态 。点击按钮后,修改函数的状态。感觉没问题,但是当点击之后会报一个错误。
this是undefined,自然就不能调用setState方法了。这是为什么呢?
因为handleClick方法并不是实例后对象调用的,而是直接调用的。它不同于render()方法和生命周期函数。这些函数是类主键实例后自动调用的,是实例化的对象调用的。而handleClick是我们自己声明的函数。它作为回调函数给了click事件,所以当类实例化之后,它并没有触发。后来当触发单击事件后,仅仅是作为一个函数调用。并没有通过实例调用,所以this就是undefined。
我们可以在render中打印一下this
可以发现函数定义到了类的原型上面,所以只能通过实例对象调用才能生效。
解决方法一 通过箭头函数
声明函数的时候使用箭头函数声明,因为箭头函数没有自己的this。它的this取决于父级的this指向。
import React, { Component } from 'react';
export default class App extends Component {
state= {
name: '张三'
}
handleClick = () => {
console.log(this);
this.setState({name:'李四'})
}
render() {
return (
<div>
<h1>我的名字是{this.state.name}</h1>
<button onClick={this.handleClick}>点击我改名字</button>
</div>
);
}
}
this的值就不再是undefined了,而且可以看出来函数被定义到了,类实例化本身上,而不是原型上
方法二 利用bind()方法
import React, { Component } from 'react';
export default class App extends Component {
constructor(props){
super(props);
this.state= {
name: '张三'
}
this.handleClick = this.handleClick.bind(this); //这里是主要变化,右边的handleClick是原型上面的方法,左边的是类本身
}
handleClick () {
console.log(this);
this.setState({name:'李四'})
}
render() {
return (
<div>
<h1>我的名字是{this.state.name}</h1>
<button onClick={this.handleClick}>点击我改名字</button>
</div>
);
}
}
我们可以看一下this
this.handleClick = this.handleClick.bind(this);
就是在类本身上也添加了一个handleClick方法,bind()可以改变this的指向并且返回一个函数。
把改变this的方法赋值给类的同名方法handleClick,下面单击事件触发的就是类本身的方法。
通过原生js演示问题
class Car {
name = '奔驰';
run(){
console.log(this.name+'在奔跑');
}
}
const c = new Car();
c.run()
能够正常执行,输出结果。因为现在是使用实例调用的方法
class Car {
name = '奔驰';
run(){
console.log(this.name+'在奔跑');
}
}
const c = new Car();
c.run()
const fun = c.run;
fun()
不能正常执行,因为函数是被直接调用的。所以this为undefined
利用bind()改变this的指向,并且赋值给类实例本身。
class Car {
name = '奔驰';
constructor(){
this.run = this.run.bind(this)//这里右边的run方法是原型上的方法,左边的run是类本身的
}
run=()=>{
console.log(this.name+'在奔跑');
}
}
const c = new Car();
c.run()
const fun = c.run;
bind方法的使用
class Car {
name = '奔驰';
run(){
console.log(this.name+'在奔跑');
}
}
const c = new Car();
c.run()
const fun = c.run;
fun.bind(Car)
利用箭头函数,方法也会被定义到类的实例上
class Car {
name = '奔驰';
run=()=>{
console.log(this.name+'在奔跑');
}
}
const c = new Car();
c.run()
const fun = c.run;
fun()