React的constructor super作用是什么?为什么要进行bind绑定?

本文探讨了React组件中constructor和super的作用。constructor用于初始化组件状态,而super(props)确保了子类能正确继承父类的属性。不写constructor时,React会自动添加并调用super。如果不调用super,子类的this会报错,因为ES6继承机制要求先调用super()。同时,只有在super后才能使用this。传递props是为了在构造函数中访问this.props。另外,React事件处理中,由于this指向问题,常需要bind或使用箭头函数绑定上下文。

最近有些迷惑一个事情,就是在写react组件的时候,有时候写constructor,有时候不写,呃呃呃呃呃,虽然不起眼,但是这到底是一个什么机制呢,好好研究了一下,发现涉及到的东西还不少,这并不是出现在react的东西,而是涉及到类和继承的问题的,决定写下来总结一下。虽然对于使用并不影响,但是只知其然不知其所以然,慢慢就会变得迷茫。。。。
参考文章
Why Do We Write super(props)?
阮一峰:Class 的继承
为什么在React Component需要bind绑定事件
MDN类体和方法定义

1.constructor方法到底是啥?
MDN对类和构造函数的解释中说明

constructor方法是一个特殊的方法,这种方法用于创建和初始化一个由class创建的对象。
一个构造函数可以使用 super 关键字来调用一个父类的构造函数

2.写不写?

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

以上是react官网粘贴下来的代码,但是在实际写的时候,不写constructor,super也是没有问题的,并不会影响的执行。不写 constructor(props) {super(props);的部分,并不是我们在运行中不再运行了,如果子类没有定义constructor()方法,这个方法会默认添加,并且里面会调用super()。也就是说,不管有没有显式定义,任何一个子类都有constructor()方法。

class ColorPoint extends Point {
}
// 等同于
class ColorPoint extends Point {
  constructor(...args) {
    super(...args);
  }
}

3.如果写了constructor,就必须写super
如果只写了constructor,而不写super,使用this就会出现报错在这里插入图片描述
为什么子类的构造函数,一定要调用super()?原因就在于 ES6 的继承机制,与 ES5 完全不同。

ES5 的继承机制,是先创造一个独立的子类的实例对象,然后再将父类的方法添加到这个对象上面,即“实例在前,继承在后”。
ES6 的继承机制,则是先将父类的属性和方法,加到一个空的对象上面,然后再将该对象作为子类的实例,即“继承在前,实例在后”。这就是为什么 ES6 的继承必须先调用super()方法,因为这一步会生成一个继承父类的this对象,没有这一步就无法继承父类。

这意味着新建子类实例时,父类的构造函数必定会先运行一次。

另一个需要注意的地方是,在子类的构造函数中,只有调用super()之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,必须先完成父类的继承,只有super()方法才能让子类实例继承父类。

super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B的实例,因此super()在这里相当于A.prototype.constructor.call(this)。
4.加不加props?
只有一个理由需要传递props作为super()的参数,那就是你需要在构造函数内使用this.props
解释引自 What’s the difference between “super()” and “super(props)” in React when using es6 classes?

There is only one reason when one needs to pass props to super():
When you want to access this.props in constructor.
(Which is probably redundant since you already have a reference to it.)

 constructor(props){
        super(props)
        this.state = {
            name :this.props.name。//在constructor中访问 不加props会报错
        }
    }
    componentDidMount(){
        console.log(this.props.name) //不在constructor中 不加props不会报错
    }

写到这里,想起来一个事情,就是react中的函数推荐使用bind进行事件绑定,但是在使用箭头函数以后就不再需要再绑定了,大家都知道是因为this的指向发生了变化导致this报错,但是为什么会发生指向变化,this又指向了哪里呢?
5.react中的事件指向问题。
其实这个问题也是js的问题,令人用起来比较麻烦的this问题。最直接的一点就是谁调用this就会指向谁,具体问题再具体分析啦!

<button onClick={ this.handleClick } >Hello</button>

React 通过 React.createElement 方法模拟 document.createElement 来创建 DOM(当然React创建的是虚拟DOM)。 属性中 onClick 指向 this.handleClick 方法,看起来都没有问题。
但是render方法中被Babel编译后的样子:

 render() {
    return React.createElement(
      'button',
      { onClick: this.handleClick },
      'Hello'
    );
  }

此时的onClick即是中间变量,相当于把函数传递给了onClick这个变量,等点击的时候会调用方法,所以在调用的时候其实是谁调用onclick的问题,在React class组件中,在执行click事件时类似于 element.addEventListener(‘click’, callback, false),该callback失去了隐式绑定的上下文,指向了全局对象,严格模式下的this值为 undefined。
参考MDN中类的说明

当调用静态或原型方法时没有指定 this 的值,那么方法内的 this 值将被置为 undefined。即使你未设置 “use
strict” ,因为 class 体内部的代码总是在严格模式下执行。

所以要绑定this。使用bind或者使用箭头函数,使this绑定在当前的上下文。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值