美文网首页
05:为什么React的构造函数里总是要bind(this)?

05:为什么React的构造函数里总是要bind(this)?

作者: 赛博剑仙_李玄器 | 来源:发表于2020-01-03 11:10 被阅读0次

    在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(属性) 传递给下级组件,这些组件可能需要额外的重复渲染。我们通常建议在构造函数中进行绑定,以避免这类性能问题。

    相关文章

      网友评论

          本文标题:05:为什么React的构造函数里总是要bind(this)?

          本文链接:https://www.haomeiwen.com/subject/ashzoctx.html