基础概念
高级程序设计书中有描述 JS 实现继承的方案有五种
- 原型链继承
- 盗用构造函数继承
- 组合继承
- 寄生式继承
- 寄生式组合继承
组合继承和寄生式组合继承使用的继承场景不一致
组合继承适用于构造函数来创建属性、方法
寄生式组合继承适用于在使用既有对象进行继承、不需要构造函数创建属性、方法的场景
typescript 修改构建产物为 ES5 版本后、class 继承的实现就是基于寄生式组合继承
class A {
name: string
constructor(name) {
this.name = name
}
colors: string[] = ['red']
}
class B extends A {
constructor(name: string) {
super(name)
}
}
const b = new B('xxxx')
编译产物
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var A = /** @class */ (function () {
function A(name) {
this.colors = ['red'];
this.name = name;
}
return A;
}());
var B = /** @class */ (function (_super) {
__extends(B, _super);
function B(name) {
return _super.call(this, name) || this;
}
return B;
}(A));
var b = new B('xxxx');
梳理后
var __extends = (function () {
// 拷贝目标
var extendStatics = function (d, b) {
// Object.setPrototypeOf ||
// ({ __proto__: [] } instanceof Array &&
// function (d, b) {
// d.__proto__ = b
// }) ||
// function (d, b) {
// for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]
// }
// return extendStatics(d, b)
// var xxxx = function () {
// xxxx = '123'
// console.log(xxxx)
// }
// xxxx() // 123
// 这里是 extendStatics 的兼容实现
// 支持 Object.setPrototypeOf 语法就使用这个语法
// extendStatics 是函数内部作用域的变量 var 关键字可以没有只是和变量同名
var extendStatics
if (Object.setPrototypeOf) {
extendStatics = Object.setPrototypeOf
return extendStatics(d, b)
}
// setPrototypeOf 的兼容实现
var o = {
__proto__: []
}
var a = function (d, b) {
d.__proto__ = b
}
// 支持 __proto__ 方式修改原型链指向就使用 a 函数也就是 setPrototypeOf 的替补实现
if (o instanceof Array) {
extendStatics = a
return extendStatics(d, b)
}
// 拷贝对象属性的方法
function xxx(d, b) {
for (var p in b) {
if (Object.prototype.hasOwnProperty.call(b, p)) {
d[p] = b[p]
}
}
}
// extendStatics 的兜底实现
extendStatics = xxx
return extendStatics(d, b)
}
// 返回具体的继承实现函数
return function (d, b) {
if (typeof b !== 'function' && b !== null)
throw new TypeError(
'Class extends value ' + String(b) + ' is not a constructor or null'
)
// 拷贝b 到 d
extendStatics(d, b)
function __() {
this.constructor = d
}
// d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new __())
if (b === null) {
d.prototype = Object.create(b) // d 的原型指向是 null
} else {
__.prototype = b.prototype
// 这里就是寄生式继承的方案了
d.prototype = new __()
}
}
})()
var A = /** @class */ (function () {
function A(name) {
this.colors = ['red']
this.name = name
}
return A
})()
// 寄生式组合继承
var B = /** @class */ (function (_super) {
// 寄生式继承
__extends(B, _super)
function B(name) {
// 盗用构造函数继承
return _super.call(this, name) || this
}
return B
})(A)
var b = new B('xxxx')
console.log(b)
最后:书真是个好东西啊