🌑 [ECMAScript6]23. Class继承
简介
属性和方法的继承
可以继承静态方法 静态属性
不可以继承私有方法 私有属性
javascriptCopy
class Foo {
#p = 1;
#m() {
console.log('hello');
}
}
class Bar extends Foo {
constructor() {
super();
console.log(this.#p); // 报错
this.#m(); // 报错
}
}super关键字
__proto__ prototype
class作为构造函数的语法糖同时具有__proto__ 和 prototype 属性,class的__proto__ 是构造函数的继承,总是指向父类。prototype.__proto__ 是方法的继承总是指向父类的prototype。

继承的实现模式如下。
javascriptCopy
class A {...}
class B extends A {...}
Object.setPrototypeOf(B, A)
Object.setPrototypeOf(B.prototype, A.prototype)
// setPrototypeOf 方法实现
Object.setPrototypeOf = function (obj, proto) {
obj.__proto__ = proto;
return obj;
}实例的__proto__属性
实例__proto__指向类 类的prototype 。所以实例的__proto__.__proto__ 指向父类prototype。所以子实例的__proto__.__proto__ 也指向父实例的__proto__ 。
javascriptCopy
class Point {...}
class ColorPoint extends Point {...}
var p1 = new Point(2, 3);
var p2 = new ColorPoint(2, 3, 'red');
p1.__proto__ === Point.prototype // true
p2.__proto__ === ColorPoint.prototype // true
p2.__proto__.__proto__ === p1.__proto__ // true
原生构造函数的继承
ECMAScript中原生构造函数为。
ES5 原生构造函数是不能继承的。比如
javascriptCopy
function MyArray() {
Array.apply(this, arguments);
}
MyArray.prototype = Object.create(Array.prototype, {
constructor: {
value: MyArray,
writable: true,
configurable: true,
enumerable: true
}
});
var colors = new MyArray();
colors[0] = "red";
colors.length // 0
colors.length = 0;
colors[0] // "red"之所以会发生这种情况,是因为子类无法获得原生构造函数的内部属性,通过Array.apply()或者分配给原型对象都不行。原生构造函数会忽略apply方法传入的this,也就是说,原生构造函数的this无法绑定,导致拿不到内部属性。
ES5 是先新建子类的实例对象this,再将父类的属性添加到子类上,由于父类的内部属性无法获取,导致无法继承原生的构造函数。比如,Array构造函数有一个内部属性[[DefineOwnProperty]],用来定义新属性时,更新length属性,这个内部属性无法在子类获取,导致子类的length属性行为不正常。
ES6 允许继承原生构造函数定义子类,因为 ES6 是先新建父类的实例对象this,然后再用子类的构造函数修饰this,使得父类的所有行为都可以继承。下面是一个继承Array的例子。
