参考资料
(22条消息) JavaScript各种继承,原型继承,构造函数继承,组合继承,寄生组合,ES6继承,我能学会你也可以_不见浅诗的博客-CSDN博客
面试官:Javascript如何实现继承? | web前端面试 - 面试官系列 (vue3js.cn)
JavaScript深入之继承的多种方式和优缺点 · Issue #16 · mqyqingfeng/Blog (github.com)
《JavaScript高级程序设计》
原型链继承
function father(){
this.age = 21;
this.person = [1,2,3];
}
father.prototype.getPerson = function(){
return this.person;
}
function son(){
}
let f = new father();
son.prototype = f;
/* 继承完之后,在定义son自己的prototype */
let SON = new son();
f.person[0] = "fujiaxu";
console.log(SON.getPerson());// fujiaxu
缺点:
子类和父类共享属性,如果这些属性不是基本类型,那么它们之间的修改将会被共享。
构造函数继承
function father(){
this.age = 21;
this.person = [1,2,3];
}
function son(){
father.call(this);
}
let SON = new son();
console.log(SON);
缺点:
不能继承原型上的方法。
组合继承
这是把前面两种继承方式结合起来。
function father() {
this.age = 21;
this.person = [1, 2, 3];
}
father.prototype.say = function () {
return "hello";
};
function son() {
father.call(this);
}
son.prototype = new father();// 这里为什么是new,需要好好想想
son.prototype.constructor = son;
// 可以写自己的原型上的方法了
let SON = new son();
console.log(SON,SON.say());
缺点:
父类执行了两次
原型式继承
借助Object.create
方法实现普通对象的继承
这种继承方式的缺点也很明显,因为Object.create
方法实现的是浅拷贝,多个实例的引用类型属性指向相同的内存,存在篡改的可能。
寄生式继承
寄生式继承在上面继承基础上进行优化,利用这个浅拷贝的能力再进行增强,添加一些方法。
function createObj (o) {
var clone = Object.create(o);
clone.sayName = function () {
console.log('hi');
}
return clone;
}
寄生组合式继承(最优的继承方式)
这是在组合继承的基础上进行优化,因为组合继承调用了两次构造函数(call 和 new father()),
对于call的调用,这是不可避免的,所以我们要想办法来优化掉new father() 这一步,我们其实只是想要间接访问原型,所以我们就可以使用Object.create(prototype,propertyObject)
function father() {
this.age = 21;
this.person = [1, 2, 3];
}
father.prototype.say = function () {
return "hello";
};
function clone(father,son){
son.prototype = Object.create(father);
son.prototype.constructor = son;
}
function son() {
father.call(this);
}
clone(father,son);
let SON = new son();
console.log(SON);
Object.create()的原理
Object.myCreate = function (proto, propertyObject = undefined) {
if (propertyObject === null) {
// 这里没有判断propertyObject是否是原始包装对象
throw 'TypeError'
} else {
function Fn () {} // 空构造函数
// 该对象是没有构造函数的,或者说,该对象的构造函数式Object
Fn.prototype = proto
const obj = new Fn()
if (propertyObject !== undefined) {
Object.defineProperties(obj, propertyObject)
}
if (proto === null) {
// 创建一个没有原型对象的对象,Object.create(null)
obj.__proto__ = null
}
return obj
}
}
ES6 的class
对于ES6的class 也是采用了寄生组合式继承的方式。