我目前所用过的常用的js继承有7种,分别为,原型继承,构造继承,拷贝继承,实例继承,组合继承,寄生组合继承,class继承.下面将逐一分析各种继承的优缺点。
先写一个父类以便继承。
function Parent(name) {
this.name = name || 'parent';
this.sleep = function () {
console.log(this.name + '跟淼在一起睡觉');
}
}
1、原型继承
就是把son的原型改为parent的new实例,来实现继承。
function Son() { }
Son.prototype = new Parent();
//测试
var son = new Son();
console.log(son.name);//parent
son.sleep();//调用父类的方法 //parent跟淼在一起睡觉
console.log(son instanceof Parent); //true 与父同类型
console.log(son instanceof Son); //true
这种方式继承的缺点是:上面使用原型链来继承,没办法使属性私有化。属性都是共享的。一改全改。
2、借用构造继承
在son里面,把parent的this指向变成son的this指向,来实现继承
function Son(name) {
Parent.call(this);
this.name = name || 'Parent';
}
var son = new Son('fxq');
console.log(son.name); //fxq
son.sleep(); //fxq跟淼在一起睡觉
console.log(son instanceof Parent); //false
console.log(son instanceof Son); //true
这种方式继承的缺点是:只能继承属性,父类的方法不能共享,就是每个子类调用方法,但方法都不同,会造成内存泄露。
3、实例继承
function Son() {
var instance = new Parent();
return instance;
}
var son = new Son()
console.log(son.name) //传不了参 parent
son.sleep(); //parent跟淼在一起睡觉
console.log(son instanceof Parent); //true
console.log(son instanceof Son); //false
4、组合继承
是将原型继承和构造继承组合起来实现继承。即将parent的指向改到son上,也将son原型改为parent实例。
function Son(name) {
Parent.call(this);
this.name = name || 'Parent';
}
Son.prototype = new Parent();
console.log(Son.prototype.constructor);
Son.prototype.constructor = Son;//重新将构造函数指向改回Son函数,没改之前指向Parent
console.log(Son.prototype.constructor);
var son = new Son('fxq');
console.log(son.name); //fxq
son.sleep(); //fxq跟淼在一起睡觉
console.log(son instanceof Parent); //true
console.log(son instanceof Son); //true
这种继承方法解决了上面的问题,但缺点是父类原型对象被调用了两次,浪费了内存。
浏览器显示结果
ƒ Parent(name) {
this.name = name || 'parent';
this.sleep = function () {
console.log(this.name + '跟淼在一起睡觉');
}
}
Untitled-1.html:59 ƒ Son(name) {
Parent.call(this);
this.name = name || 'Parent';
}
Untitled-1.html:61 fxq
Untitled-1.html:13 fxq跟淼在一起睡觉
Untitled-1.html:63 true
Untitled-1.html:64 true
5、寄生组合继承
//寄生组合继承
function Son(name) {
Parent.call(this,name);
this.name = name || 'Parent';
}
//抱在iief里面
(function () {
var Super = function () { };
Super.prototype = Parent.prototype;
Son.prototype = new Super(); //这是找个中间量吧
})();
var son = new Son('fxq');
console.log(son.name);
son.sleep()
console.log(son instanceof Parent); // true
console.log(son instanceof Son); //true
这种方法继承几乎没有缺点,很完美,但是就是实现复杂。
6、ES6 class继承
class Son extends Parent {
constructor(name) {
super(name);
//super(name) 就是parent.call(this,name);
this.name = name || 'Parent';
}
}
var son = new Son('fxq');
console.log(son.name);
son.sleep()
console.log(son instanceof Parent); // true
console.log(son instanceof Son); //true
这种继承是使用ES6class语法糖,将寄生组合继承简化。
super(name) 就是parent.call(this,name);
7、拷贝继承
拷贝继承就是利用递归实现深拷贝,这里不多做赘述。