class的继承

extends

class Point {
}

class ColorPoint extends Point {
}

通过extends关键字,实现子类对父类的继承

但是在继承父类时,必须使用super关键字,调用父类的构造方法,首先生成一个父类的this对象,得到与父类相同的属性或方法,再对其进行加工,添加自己的属性和方法,才能得到自己的this对象。

class Point {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            }
        }
        class ColorPoint extends Point {
            constructor(x, y, color){
                super(x, y);
                this.color = color;
            }
        }

在子类中,必须首先使用super,才能使用this关键字,因为this需要基于super先生成再改造。如果以上代码将this.color = color放到super之前,会报错。

通过子类生成的实例,同时是父类和子类的实例

子类会继承父类的静态方法。

Object.getPropertyOf()

可以用来获取子类的父类,从而判断一个类是否继承了另一个类

Object.getPropertyOf(ColorPoint) === Point // true

 类的prototype和__proto__

Class作为构造函数的语法糖,同时具有prototype和__proto__属性,存在两条继承链

class father{
}
class son extends father{
}
son.__proto__ === father //true
son.prototype.__proto__ === father.prototype // true

这样的结果是因为,类的继承是如下方式实现的

class A{}
class B extends A{}

Object.setPropertyOf(B.prototype, A.prototype);
Object.setPropertyOf(B, A);

而setPropertyOf方法的实现如下:

Object.setPropertyOf = funtion(obj, proto){
  obj.__proto__ = proto;
  return obj;    
}

因此,以上类的继承

B.prototype.__proto__ = A.prototype
B.__proto__ = A

只要的内部有prototype属性的函数都能被继承,而所有的函数都有prototype属性,所以任何函数都能被继承

当A类作为基类时,其就是一个普通的函数,因此直接继承Function.prototype。而这个基类创建的实例是一个空对象,A.prototype__proto__又指向了Object.prototype

class A{}
A.__proto__ === Function.prototype // true
A.prototype.__proto__ === Object.prototype  //true

实例的__proto__属性

class P1{
constructor(name){
this.name = name
}
sayHi(){
console.log('hi~p1')
}
}
class P2 extends P1{

}
var p1 = new P1('ashen');
var p2 = new P2();
console.log(p2.__proto__.__proto__ === p1.__proto__) // true

子类实例的原型的原型,指向父类实例的原型

正因如此,通过在子类实例的原型的原型可以更改父类的方法。但不能更改父类的实例属性

p2.__proto__.__proto__.sayHi = function () {
            console.log('hi~p2')
        }
        p2.__proto__.__proto__.name = 'xing'
        p1.sayHi() // hi~p2
     console.log(p1.name) // ashen

构建原型构造函数的子类

在ES5中,继承都是先创建子类的this,再将父类的属性添加到子类上。然而父类的内部属性无法获取,也就无法继承原生的构造函数

而在ES6中,是先创建父类的this,然后用子类的属性和方法修饰this。所以继承了父类所有的内部属性。因此在ES6中可以构造原型构造函数的子类,如下实现数组构造函数的继承

class myArray extends Array{
            constructor(...args){
                super(...args);
            }
        }

        var arr = new myArray();
        arr[0] = 12;
        console.log(arr.length);
        arr.length = 0;
        console.log(arr[0]);

既然可以继承数据类型的构造函数,那么就可以在此基础上定义自己的数据结构

但是在继承Object构造函数时有一个注意点

class myObj extends Object{
            constructor(){
                super(...arguments)
            }
        }
        var o = new myObj({attr: true});
        console.log(o.attr) // undefined

无法通过super向父类构造函数传参。这是因为ES6中改变了Object构造函数的设置,当不是通过new Object()创建对象时,ES6就规定Object()构造函数忽略参数

posted @ 2020-04-17 16:49  ashen1999  阅读(419)  评论(0编辑  收藏  举报