最近在复习JS知识,看到继承的时候,回去翻了一下《高级JavaScript程序设计》,顺便整理了一下书中的知识点,方便自己理解。
基于原型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17function Parent() {
this.name = 'tom';
}
Parent.prototype.sayName = function() {
return this.name;
}
function Child() {
this.name = 'jack';
}
Child.prototype = new Parent();
var child = new Child();
child.sayName() // jack- 父类里面的引用类型的属性会被子类的实例修改,影响到其他子类实例
- 子类实例化的时候无法向父类传递参数
基于构造函数
1
2
3function Child() {
Parent.call(this)
}- 父类原型被丢失
组合继承
1
2
3
4
5
6function Child() {
// 继承属性
Parent.call(this)
}
Child.prototype = new Parent(); // 继承方法- 会调用两次父类构造函数
原型式继承
1
2
3
4
5
6
7
8
9
10
11
12function object(o){
function F(){}
F.prototype = o;
return new F();
}
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = object(person);- 可以理解为
Object.create()
- 借助原型可以基于已有的对象创建新对象。
- 从本质上讲,
object()
对传入其中的对象执行了一次浅复制
- 可以理解为
寄生式继承
创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function createAnother(original){
var clone = object(original); //通过调用函数创建一个新对象
clone.sayHi = function(){ //以某种方式来增强这个对象
alert("hi");
};
return clone; //返回这个对象
}
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"- 使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率;这一点与构造函数模式类似。
寄生组合式继承
即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24function inheritPrototype(Child, Parent){
var prototype = object(Parent.prototype); //创建对象
prototype.constructor = Child; //增强对象
Child.prototype = prototype; //指定对象
}
function Parent(name){
this.name = name;
}
Parent.prototype.sayName = function(){
alert(this.name);
};
function Child(name, age){
Parent.call(this, name); // 构造函数继承属性
this.age = age;
}
inheritPrototype(Child, Parent); // 继承原型上的方法
Child.prototype.sayAge = function(){
alert(this.age);
};- 第一步是创建超类型原型的一个副本。
- 第二步是为创建的副本添加
constructor
属性,从而弥补因重写原型而失去的默认的constructor
属性。 - 最后一步,将新创建的对象(即副本)赋值给子类型的原型。