1.class继承简介
-
1.1class可以同过extends关键字来实现继承。
{ class Point { } class ColorPoint extends Point{ } }
-
1.2子类必须再constructor方法中调用super方法,否则新建实力会报错。这是因为子类没有自己的this对象,而是继承父类的this对象。
{
class Point {} class ColorPoint extends Point{ constructor(){ //没有使用super关键字 } } let cp1 = new ColorPoint(); //ReferenceError //Must call super constructor in derived class //before accessing 'this' or returning from derived constructor
}
-
1.3 ES5 和 ES6的区别
ES5继承的实质是先创造子类的实例对象this,然后将弗雷德方法添加到this上去。(parent,app(this))
ES6的实质是先创造父类的实例对象this,然后再用子类的构造方法修改this。 -
1.4再子类的构造函数中,只有调用super之后才可以使用this关键字。
{ class Point { constructor (x,y){ this.x = x; this.y = y; } sum(x,y){ return x + y; } } class ColorPoint extends Point { constructor(x,y,color){ // this.color = color; //ReferenceError super(x,y); this.color = color; }
}
let cp = new ColorPoint(2,10,‘red’);
//cp ColorPoint {x: 2, y: 10, color: “red”}
cp.sum(2,3);
//5
} -
1.5 子类的实例同时是子类和父类的实例。
{ cp instanceof ColorPoint //true cp instanceof Point //true
}
2.Object.getPrototypeOf()
Object.getPrototypeOf()可以从子类上获取父类
{
Object.getPrototypeOf(ColorPoint) === Point
//true
}
3.super关键字
super这个关键字既可以当作函数使用也可以当作对象使用。
-
3.1 super作为函数调用时代表父类的构造函数。
ES6规定子类constructor必须执行一次super函数
super代表了父类的构造函数,但是返回的是子类的实例,即super内部的this指向子类,因此super相当于{ A.prototype.constructor.call(this); } { class A { constructor () { console.log(new.target.name); } } class B extends A { constructor(){ super(); } } let p1 = new A(); //A let p2 = new B(); //B
}
// 上面的代码中,new.target指向当前正在执行的函数。可以看到super执行时内部的this指向B
-
3.2 super作为对象时在普通方法中指向父类的原型对象;在静态方法中指向父类。
{ class A { constructor () { } sayName(){ return 'name' } } class B extends A { constructor(){ super(); console.log(super.sayName()); } } new B(); //name console.log(A.prototype.sayName()); //name
}
//这时候就是将super当作一个对象来使用,指向A。prototype,所以super.p()相当于A.prototype.p()
4.类的prototype属性和__proto__属性
-
4.0 ES5中每一个对象都有__proto__属性指向对应的构造函数的protype属性,
ES6同时又prototype属性和__proto__属性,所以存在两条继承链。 -
4.1 子类的__proto__属性表示构造函数的继承,总是指向父类。
-
4.2 子类prototype属性的__proto__属性表示方法的继承,指向父类的prototype属性。
{
class A {} class B extends A { } console.log(B.__proto__ === A); //true console.log(B.prototype.__proto__ === A.prototype) //true console.log(B.constructor === Function); //true
}
-
4.3 类的继承的模式实现
{
class A {}class B {} //B的实例继承A的实例 Object.setPrototypeOf(B.prototype, A.prototype) //B的实例继承A的静态属性 Object.setPrototypeOf(B,A); console.log(B.__proto__ === A); //true console.log(B.prototype.__proto__ === A.prototype) //true //Object.setPrototypeOf的实现 Object.setPrototypeOf = function (obj, proto){ obj.__proto__ = proto; return obj; }
}
-
4.4 extends的继承目标只要有Prototype的属性的函数就能被继承。
-
4.5 实例的__proto__属性
子类实例的__proto__属性的__proto__属性指向父类的__proto__属性;
子类原型的原型就是父类的原型。
{
class A {}class B extends A { constructor(){ super() } } let a1 = new A(); let b1 = new B(); console.log(b1.__proto__.__proto__ === a1.__proto__) //true
}
-
5.Mixin模式的实现
Mixin模式指的是将多个类的接口"混入"另外一个类。ES6如下实现
{
function mix(…mixins){
class Mix {}for(let mixin of mixins){ copyProperties(Mix,mixin); copyProperties(Mix.prototype, mixin.prototype); } return Mix; } //copyProperties function copyProperties(target, source){ for(let key of Reflect.ownKeys(source)){ if( key !== "constructor" && key !== "prototype" && key !== "name" ){ let desc = Object.getOwnPropertyDescriptor(source, key) Object.defineProperty(target, key, desc); } } } class objToClass extends mix(obj1,obj2){ }
}
// 上面的mix函数可以将多个对象合并为一个类.使用的时候继承这个类就好了。
-
参考文献<ES6标准入门>