继承的几种形式

简单原型链继承

1
2
3
4
5
6
7
function Super(){
this.name = "Jack";
}
function Sub(){
//...
}
Sub.prototype = new Super(); //核心

缺点:修改sub1.name后sub2.name也变了,因为来自原型对象的引用属性是所有实例共享的。Sub.prototype.constructor变成了Super

借用构造函数式继承

1
2
3
4
5
6
7
8
9
10
function Super(val){
this.val = val;
this.fun = function(){ //实例函数
//...
}
}
function Sub(val){
Super.call(this,val); //核心
//...
}

缺点:无法实现函数复用,每个子类实例都持有一个新的fun函数,太多了就会影响性能,内存爆炸。。

组合式继承(原型+借用构造函数)

1
2
3
4
5
6
7
8
9
10
11
12
function Super(val){
this.val = val;
}
//原型函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(val){
Super.call(this,val); //核心
//...
}
Sub.prototype = new Super(); //核心

缺点:子类原型上有一份多余的父类实例属性,因为父类构造函数被调用了两次,生成了两份,而子类实例上的那一份屏蔽了子类原型上父类的。。。又是内存浪费。

原型式继承

基本想法:借助原型可以基于已有的对象创建新对象,同时还不必须因此创建自定义的类型。

1
2
3
4
5
function createObj(obj){
function F(){}
F.prototype = obj;
return new F();
}

5、寄生式继承

基本思想:创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真正是它做了所有工作一样返回对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function Super(){
this.val = 1;
this.arr = [1];
}
function create(obj){
var F = function(){};
F.prototype = obj;
return new F();
}
function getSubObject(obj){
//创建新对象
var clone = create(obj); //核心
//增强
clone.attr1 = 1;
clone.attr2 = 2;
//clone.attr3...
return clone;
}
var sub = getSubObject(new Super());
alert(sub.val); //1
alert(sub.arr); //1
alert(sub.attr1); //1

给原型式继承穿了个马甲而已,看起来更像继承了(上面介绍的原型式继承更像是对象复制)

注意:create函数并不是必须的,换言之,创建新对象 -> 增强 -> 返回该对象,这样的过程叫寄生式继承,新对象是如何创建的并不重要(用create生的,new出来的,字面量现做的。。都可以)

优点:

  1. 还是不需要创建自定义类型

缺点:

  1. 无法实现函数复用(没用到原型,当然不行)

寄生组合式继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Super(val){
this.val = val;
}
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(val){
Super.call(this,val); //核心
//...
}
Sub.prototype = Object.create(Super.prototype); //核心
Sub.prototype.constructor = Sub; //核心
或者:
function F(){}
Super.prototype = F.prototype;
Sub.prototype = new F();
Sub.prototype.constructor = Sub;

es6的class继承方式

1
2
3
4
5
6
7
8
class A{
}
class B extends A{
}
B.__proto__ === A; //true
B.prototype.__proto__ === A.prototype; //true;

es6引入了class、extends、super、static(部分为ES2016标准)


本文结束,感谢阅读。

本文作者:melody0z
本文链接:https://melodyvoid/JavaScript/several-forms-of-sucesion.html
欢迎转载,转载请注明文本链接

坚持原创技术分享,您的支持将鼓励我继续创作!