原型链继承

原型链的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var A  = {
name:'A',
color:['red','green'],
sayA:function(){
console.log('from A');
}
};

//使用Object.create方法先复制一个对象
var B = Object.create(A,{
name:{
value:'B'
}
});
console.log(B)//Object{name:'B'}
B.sayA()//'from A'

寄生式继承

创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function createA(name){
//创建新对象
var obj = Object(name);
//增强功能
obj.sayO = function(){
console.log("from O")
};
//返回对象
return obj;

}
var A = {
name:'A',
color:['red','green','blue']
};
//实现继承
var B = createA(A);
console.log(B)//Object {name: "A", color: Array[3]}
B.sayO();//from O

寄生组合式继承

组合继承是JavaScript最常用的继承模式,组合继承最大的问题就是无论在什么情况下,都会调用两次构造函数:一次是在创建子类型原型时,另一次是在子类型构造函数内部。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function A(name) {
this.name = name
this.color = ['red','green'];
}
A.prototype.sayA = function(){
console.log("form A")
}
function B(name,age){
//第二次调用了A
A.call(this,name);
this.age = age;
}

//第一次调用了A
B.prototype = new A();
B.prototype.sayB = function(){
console.log("form B")
}


var b1 = new B('Mike',12);
var b2 = new B('Bob',13);
console.log(B.prototype)//A {name: undefined, color: Array[2]}

借用构造函数

可以通过apply()或call()方法执行构造函数

1
2
3
4
5
6
7
8
9
10
11
12
function Person(){
this.names = ["A","B","C"];
}
function Student(){
Person.call(this);
}

var s1 = new Student();
s1.names.push("D");
alert(s1.names);//A,B,C,D
var s2 = new Student()
alert(s2.names);//A,B,C

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

结合使用原型链与借用构造函数的优点,组合而成的一个模式。结合了两方的优点,即原型链继承方法,而在构造函数继承属性

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
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getName = function() {
return this.name
}
Person.prototype.getAge = function() {
return this.age;
}

function Student(name, age, grade) {
// 构造函数继承
Person.call(this, name, age);
this.grade = grade;
}

// 原型继承
Student.prototype = Object.create(Person.prototype, {
// 不要忘了重新指定构造函数
constructor: {
value: Student
},
getGrade: {
value: function() {
return this.grade
}
}
})


var s1 = new Student('ming', 22, 5);

console.log(s1.getName()); // ming
console.log(s1.getAge()); // 22
console.log(s1.getGrade()); // 5

ES6继承

ES6封装了class,extends关键字来实现继承,内部的实现原理其实依然是基于原型链,不过经过一层封装后,Javascript的继承得以更加简洁优雅地实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Animal{
//构造函数
constructor(props){
this.name=props.name||'未知';
}

eat(){
alert(this.name+"在吃东西...");
}
}

//class继承
class Bird extends Animal{
//构造函数
constructor(props){
//调用实现父类的构造函数
super(props);
this.type=props.type||"未知";
}

fly(){
alert(this.name+"在飞...");
}
}