React事件处理函数为什么需要手动绑定this及绑定方法

347 阅读2分钟

一,this指向(React事件处理函数为什么需要手动绑定this)

this指的是函数运行时所在的环境对象

普通函数

普通函数的this指向的是调用它的对象,而且是离谁近指向谁,可以通过call,bind,apply修改this指向。

  • 普通模式下,顶级作用域中,函数默认绑定到window上,this指向的是window
  • 严格模式下,顶级作用域中,函数默认是未定义的,this执行undefined

箭头函数

箭头函数的this指向是定义它时所在作用域的this指向,定义的时候就已经确定了,不会根据谁调用而改变,不能通过call,bind,apply修改this指向。

非严格模式下

var obj = {
    innerObj: {
        foo: function() {
            console.log(this);
        }
    }
}

obj.innerObj.foo();// {foo: ƒ}
var temp = obj.innerObj.foo;
temp();//Window {window: Window, self: Window, …}

image.png

严格模式下

'use strict'
var obj = {
    innerObj: {
        foo: function() {
            console.log(this);
        }
    }
}

obj.innerObj.foo();// {foo: ƒ}
var temp = obj.innerObj.foo;
temp();//undefined

image.png

当严格模式下将函数赋值给一个中间变量时会造成this指向丢失

import react from "react";

class News extends react.Component {

    constructor(props){
        super(props);

        this.state = {
            name: "melinda"
        }
    }

    handleClick(){
        console.log(this,this.setState({name: 'melinda啦啦啦啦'}))
    }
    

    render(){
       
        return (
            <div>
                <button onClick={this.handleClick}>修改name</button>
                <p>{this.state.name}</p>
            </div>
        )
    }
}

export default News;

会报错TypeError: Cannot read properties of undefined (reading 'setState')

结论:react使用babel将JSX和ES6转ES5的时候,默认转化之后是严格模式,此时window下面的onClick事件就相当于一个中间变量,执行onclick里面的函数时,里面的this就会指向undefined,要让this指向当前实例就需要通过箭头函数或者bind改变this的指向。

二,绑定this的四种方法

1,在构造函数中使用bind绑定this

2,在调用的时候使用bind绑定this

3,使用属性初始化器语法绑定this(使用箭头函数声明)

4,在调用的时候使用使用箭头函数绑定this

import react from "react";

class News extends react.Component {

    constructor(props){
        super(props);

        this.state = {
            name: "melinda"
        }
        //方法1
        this.handleClick1 = this.handleClick1.bind(this);
    }

    handleClick1(){
        console.log(111,this,this.setState({name: '啦啦啦啦'}))
    }
    handleClick2(name){
        console.log(111,this,this.setState({name: name}))
    }
    //方法3
    handleClick3 = ()=>{
        console.log(111,this,this.setState({name: '啦啦啦啦'}))
    }
    

    render(){
       
        return (
            <div>
                <button onClick={this.handleClick1}>构造函数中使用bind</button>
                <button onClick={this.handleClick2.bind(this,'lisi')}>调用时使用bind</button>
                
                <button onClick={this.handleClick3}>声明时使用箭头函数</button>
                <button onClick={()=> this.handleClick2('zhangsan')}>调用时使用箭头函数</button>
                <p>{this.state.name}</p>
            </div>
        )
    }
}

export default News;