继承方式
背景:父类有实例属性,也有原型链上的方法,自类要继承父类的实例属性和原型链方法,同时自类也会新定义自己的实例属性和原型链上的方法
- 组合继承
- 原型继承
- 寄生式继承
- 寄生组合继承
- ES6 Class extends
- | 类型 | 场景 | 优点 | 缺点 |
---|---|---|---|---|
1 | 组合继承 | 调用2次父类,自类原型上也获得了父类实例上的属性,造成冗余 | ||
2 | 原型继承 | 只想让一个对象与另一个对象保持类似,不兴师动众创建构造函数 | 简单 | 包含引用类型值的属性会共享相应的值 |
3 | 寄生继承 | 增强对象? | 函数没有得到复用 | |
4 | 寄生组合继承 | 调用1次父类,避免在子类原型上创造不必要的属性,同时纠正了constructor | - | |
5 | es6 class | 语义更好,代码精简,本质寄生组合继承相同 |
代码示例
原型继承
1 | var person = { |
寄生继承
1 | function createAnother(origin){ |
组合继承 vs 寄生组合继承
有用到构造函数的公共代码(1、4)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 公共代码
function SuperType(name){
this.name = name;
this.colors = ['red', 'yellow','blue']
}
SuperType.prototype.sayName = function(){
alert(this.name)
}
function SubType(name, age){
SuperType.call(this)
this.age = age
}
// 寄生组合继承
SubType.prototype = Object.create(SuperType.prototype)
SubType.prototype.constructor = SubType
// 组合继承
SubType.prototype = new SuperType()
// 公共代码
SubType.prototype.sayAge = function(){
console.log(this.age)
}
ES6 类继承
类是语法糖,完全可以看作是函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46function parent(name){
this.name = name
}
parent.prototype.say = function(){
console.log(this.name)
}
function child(name,age){
parent.call(this,name)
this.age= age
}
child.prototype= Object.create(parent.prototype,{
constructor:{value:child}
})
child.prototype.talk = function(){
console.log(this.age)
}
var c= new child('si',12)
c.__proto__ 访问子类原型方法
c.__proto__.__proto__ 访问父类原型上方法
=========================
class parent{
constructor(name){
this.name = name
}
say(){
console.log(this.name)
}
}
class child extends parent{
constructor(name,age){
super(name)
this.age=age
}
talk(){
console.log(this.age)
}
}
var c2= new child('yuan',11)