JavaScript中class继承超乎你的想象《一》

1,147 阅读2分钟

引子

在前端框架中使用类(class)继承的当属拥有强大生态的React,我们在react中自定义一个组件往往会这样子写:

class MyComponent extends React.Component{
    constructor(props){
        this.state={
            user:'React',
            display:true
        }
    }
    render(){
        return(
           <div>
              <p>{this.state.user}</p>
           </div>
        )
    }
}

上面就使用到了class继承,继承react.component的属性和方法,在服务端,我们使用nodeJs最新的框架koa2,所有的继承都是使用es6的class来进行继承。那么废话不多说,一起来看一看它的庐山真面目。

简介

class Parent{
   
}
class Child extends Parent{
    constructor(x,y,color){
        super(x,y);//调用父类的constructor(x,y)
        this.color=color;
    } 
    toString(){
        return this.color+''+super.toString();//super.toString();调用了父类的toString()方法
    }
}

上面定义了一个Child类,该类通过extends关键字继承了Parent类的所有属性和方法,constructor方法和toString方法中都出现了super关键字,它在这里表示父类的构造函数,用来新创建父类的this对象。

子类必须在constructor方法中调用super的方法,否则新建实例会报错,这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工,不调用super方法,子类就得不到this对象。

class Parent{
   /*........*/
}
class Child extends Parent{
    constructor(x,y,color){
      
    } 

}
let cp=new Child()//ReferenceError;

上面的代码中,Child 虽然继承了Parent类,但是在自己的的构造函数中没有调用super方法,导致新建实例报错。

在这里我们就得聊一聊es5和es6的继承实质,在es5的继承实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面,也就是Parent.apply(this)。而es6的继承机制完全不同,实质是先创造父类的实例对象this(所以必须调用super方法),然后使用子类的构造函数去修改this。

注意点

1.如果子类没有定义constructor方法,那么这个方法会被默认添加,如下代码,也就是说无论有没有显示定义,任何一个子类都有constructor方法。

class dog extends  Aimals{
    constructor (...args){
        super(...args)
    }
}
//两者等价
class dog extends  Aimals{
    constructor (...args){
        super(...args)
    }
}

2.另一个要注意的地方是,在子类的构造函数中,只有调用super之后才可以使用this关键字,否则会报错,这是因为子类实例的构建是基于父类实例的加工,只有super方法才能返回父类的实例。

class Animals{
   constructor (name,age)
       this.name=name;
       this.age=age;
    }  
}
class dog extends  Animals{
    constructor (name,age,color){
       this.color=color;   //ReferenceError
       super(name,age)
       this.age=age;
       this.color=color; //正确
    }
}

上面的代码,子类的constructor方法没有调用super之前就使用this关键字,结果报错,而在super之后就是正确的。