# js实现继承的方法
# 父类实现
// 定义一个动物类
function Animal(name){
this.name = name || 'Animal'
this.sleep = function(){
console.log(this.name+'正在睡觉')
}
}
// 原型方法
Animal.prototype.eat = function(food){
console.log(this.name+'正在吃'+food)
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 1.原型链继承
function Cat(){
}
Cat.prototype = new Animal()
Cat.prototype.name = 'cat'
// Test code
var cat = new Cat()
console.log(cat.name) // cat
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- 缺点
- 新增原型方法,必须先指向父类的实例
- 不能多继承
- 原型对象的引用属性共享
# 2.构造继承
function Cat(name){
Animal.call(this)
this.name = name || 'Tom'
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- 特点
- 引用属性不在公用
- 可以多继承
- 缺点
- 实例不是父类的实例
- 不能继承原型方法
- 无法实现函数复用,每个字类都有父类实例函数的副本,影响性能
# 3.实例继承
function Cat(name){
var instance = new Animal()
instance.name = name || 'Tom'
return instance
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 缺点
- 实例是父类的实例
- 不支持多继承
# 4.拷贝继承
function Cat(name){
var animal = new Animal()
for(var p in animal){
Cat.prototype[p] = animal[p]
}
Cat.prototype.name = name || 'Tom'
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
- 缺点
- 效率低
- 不支持枚举的属性,无法继承
# 5.组合继承
function Cat(name){
Animal.call(this) // 第二次父类构造函数执行
this.name = name || Tom
}
Cat.prototype = new Animal() // 第一次父类构造函数执行
Cat.prototype = Cat
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- 缺点
- 调用了两次父类构造函数,如果父类构造函数里有变量name,那么子类会生成一个,原型上也会有一个多余的
# 6. 寄生组合继承
function Cat(name){
Animal.call(this)
this.name = name || 'Tom'
}
(function(){
var Super = function(){}
Super.prototype = Animal.prototype
Cat.prototype = new Super()
Cat.prototype.constructor = Cat
})()
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 优点
- 使用一个临时函数,原型指向父类原型,而不是通过构建父类对象,这样就避免了两次调用父类构造函数,临时函数也不会包含构造内容,是一个空函数,这样原型中就不会多出父类的对象(不需要的,毕竟子类中也有)。
- 实现复杂