一、前言
以下是常见的 React 组件写法,通常有 constructor 函数和 super 函数。那么这两个函数到底有什么作用?
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Son name="jack"/>
)
}
};
class Son extends React.Component {
constructor(props) {
super(props);
console.log(props);//{name:"jack"}
}
render() {
return (
<div>子类</div>
)
}
};
二、constructor 函数分析
constructor是子类(Son)的构造函数,ES6中的类都是通过类的构造函数去添加实例的属性和方法,如果没有显式添加constructor,class关键字会隐式添加。
那么类中为什么要使用constructor?可以不用吗?
//示例1
function A(){
this.name = 'jack';
};
//等同于
class A{
name = 'jack';
}
var a=new A;
console.log(a);//{name:'jack'};
说明:示例1中A类没有使用constructor构造函数,可以new出实例对象。但是,如果需要传参,该如何处理?
//示例2
function A(name){
this.name = name;
};
//等同于
class A{
constructor(name){
this.name = name;
}
}
var a=new A('jack');
console.log(a);//{name:'jack'};
说明:示例2中可以通过A类的constructor构造函数传参。
三、super 函数分析
super方法是调用父类的构造函数。ES5中继承是先实现子类的实例对象,再通过call或apply方法绑定this调用父类方法实现继承。而ES6继承却完全不同,ES6继承是先将父类实例对象的属性和方法添加到this(所以需要调用super方法),然后再由子类的构造函数修改this。
//示例3
class A{
constructor(name){
this.name = name;
}
};
class B extends A{
constructor(age,name){
super(name);//调用父类构造函数,等同于 Object.getPrototypeOf(B).apply(this, arguments)
this.age= age;
}
};
var a=new B(123,'wxp');
console.log(a);//{age:123,name:'jack'};
说明:super方法从另一个角度可以理解为父类构造函数传参。
四、思考
开头的案例中为什么 Son 类中的 props 打印出来是{name:'jack'} ?
1. 在 React 中,执行App的render()方法(源码:var inst = this._instance;var renderedComponent = inst.render());
2. 返回createElement(Son,{name:jack},{}),得到{type:Son,props:{name:jack}}(源码:var element = {$$typeof: REACT_ELEMENT_TYPE, type: type, key: key, ref: ref, props: props, _owner: owner };);
3. 将这里的props作为参数,实例化Son(源码:var Component = this._currentElement.type;inst = new Component(publicProps, publicContext, ReactUpdateQueue));
4. 并且在后面还给实例对象又添加了一个props属性。(源码:inst.props = publicProps(这里的publicProps就是上面的{name:'jack'}))。