js继承

继承方式

背景:父类有实例属性,也有原型链上的方法,自类要继承父类的实例属性和原型链方法,同时自类也会新定义自己的实例属性和原型链上的方法

  • 组合继承
  • 原型继承
  • 寄生式继承
  • 寄生组合继承
  • ES6 Class extends
- 类型 场景 优点 缺点
1 组合继承 调用2次父类,自类原型上也获得了父类实例上的属性,造成冗余
2 原型继承 只想让一个对象与另一个对象保持类似,不兴师动众创建构造函数 简单 包含引用类型值的属性会共享相应的值
3 寄生继承 增强对象? 函数没有得到复用
4 寄生组合继承 调用1次父类,避免在子类原型上创造不必要的属性,同时纠正了constructor -
5 es6 class 语义更好,代码精简,本质寄生组合继承相同

代码示例

原型继承

1
2
3
4
5
6
7
8
9
10
11
12
var person = {  
name: 'Nicoloas',
friends:['Amy', 'Jack']
}

var person1 = Object.create(person)
person1.friends.push('Sig')

var person2 = Object.create(person)
person2.friends.push('Rachael')

console.log(person.friends) // ['Amy','Jack','Sig','Racheal']

寄生继承

1
2
3
4
5
6
7
8
9
10
11
12
13
function createAnother(origin){
var clone = Object.create(origin)
origin.sayHi = function(){

}
return clone
}

var person = {
name :'mike'
}
var anotherPerson = createAnother(person)
anotherPerson.sayHi() // hi

组合继承 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
46
function 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)