带你看懂JavaScript的继承(六) 原型式继承

简单的回顾一下,我们由原型链引出了原型模式,借用构造函数继承,再到组合继承,这是我们完善javascript继承的第一种思路。本篇开始,我们将由原型式继承引出另外一种思路,我们的目的是建立起javascript中继承的一个知识结构。本篇讲到的原型式和原型模式是不一样的,请大家谨记这一点。

道格拉斯•克罗克福德(反正JSON是他发明的)创造了这种名为原型式继承的方法。这种方法的理论基础是:借助原型,我们可以基于已有的对象创建新的对象,同时还不必因此创建自定义类型

1
2
3
4
5
function object(o){
function F(){}
F.prototype = o;
return new F();
}

很简单的一个方法,其本质就是对对传入其中的对象o进行了一次浅复制。继续看下面的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
var person ={
name: "shuai";
family: ["parents"];
}
var anotherPerson = Object(person);
anotherPerson.name = "wang";
anotherPerson.family.push("sister");

var yetAnotherPerson = Object(person);
yetAnotherPerson.name = "xu";
yetAnotherPerson.family.push("brother");

console.log(yetAnotherPerson.family); //"parents","sister","brother"

这种继承方式是要求你必须有一个对象可以作为另一个对象的基础。这样你就可以把基础对象传入Object方法中,在对得到的对象加以修改即可。就像我们上面的代码实现的一样。person就是我们的基础对象,anotherPerson和yetAnotherPerson就是我们得到新对象。person的属性这三个对象共享。

如果你基础够好,应该知道ES5中的Object.create()方法就是规范化的原型式继承。这个方法接收两个参数:第一个参数用作新对象原型的对象,就是我们的基础对象;第二个参数是可选的,代表为新对象定义的额外属性的对象。那么用Object.create()实现前面的代码就是这样的(替换我们自己定义的Oject方法即可):

1
2
3
4
5
6
7
8
9
10
11
12
13
var person ={
name: "shuai";
family: ["parents"];
}
var anotherPerson = Object.create(person);
anotherPerson.name = "wang";
anotherPerson.family.push("sister");

var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "xu";
yetAnotherPerson.family.push("brother");

console.log(yetAnotherPerson.family); //"parents","sister","brother"

第二个参数我们简单介绍如下:

1
2
3
4
5
6
7
8
9
10
11
12
var person ={
name: "shuai";
family: ["parents"];
}

var anotherPerson = Object.create(person,{
name:{
value: "wang"
}
});

console.log(anotherPerson.name); //"wang"

再详细的请大家去查阅手册,对于这个方法介绍的更详细。

如果我们只是想让一个对象与另一个对象保持相似,那么原型式继承是完全可以胜任的。但是这个方法存在的问题与我们在讲原型模式时的问题是一样的,引用值共享的问题。

讲到这里大家可能会有些迷茫,确实这很容易和前面的内容搞混,但是我建议大家,不明白的话先死记硬背下来,等我们讲完这一整条思路,你就会有所顿悟。有的时候知识就是这样的,这一页书我们没看明白,也许就是因为我们还没有看下一页。一定要缕清我们目前说到的两条继承思路。

好了,这次就说道这里,我们下期见。