前两天说明面向对象的三大特性及JS不符合面向对象,只能称作支持面向对象而已,今天我们来看看JS的原型继承。

首先我们先来看,什么是原型(vmwork):

两个物件之间的原型关系(prototype relationship)跟继承(inheritance)有关:

每个物件都可以有另一个物件作为它的原型(prototype),如此一来,前者就会继承其原型的所有特性。

一个物件藉由内部特性(property)[[Prototype]]来指定其原型。

每个物件都有这个特性,但它可能是null。由[[Prototype]]连接起来的物件串链(chain of objects)被称作原型串链(prototype chain)。

《Speaking JavaScript第十七章-物件与继承》

我相信第一次看到这段话的人肯定是满脸问号,我也是一样。

![](https://i.imgur.com/SDkfh9b.png =200x)

没关系我们一步一步慢慢来看!

简单来说,可以定义一些自动成为可让其它物件存取的属性和功能

在JS中,我们可以很容易的建立一个物件,也可以轻易的修改和删除已经指派给物件的属性。

var obj = {

a:'apple',

b:function(){},

c:{},

d:[]

};

obj.a = [];

obj.b =“banana”;

delete obj.c;

在开发过程中,我们都会尽量避免重复造轮子,也就是尽可能的重复利用现有的代码。

所以一种可重复利用的代码,并帮助我们把程序组织好的方式就是「继承」,把存在于某个物件上的功能延伸到其他物件上。

在JS中,继承就是用「原型」实作出来的。

透过原型,物件可以存取属于其他物件的属性

const Jason = {

CSS:true

};

const Turtle = {

JS:true

};

const Kai = {

Vue:true

};

我们刚刚建立了三个物件,每个物件都有一个自己才能存取的属性。

可以利用in测试物件能否存取某个属性:

“JS”in Jason;//false

“CSS”in Jason;//true

如果我们想要Json存取Turtle的JS属性,可以用Object.setPrototypeOf,需要两个参数(argument),并把第二个参数设为第一个参数的原型,所以我们可以这样做:

Object.setPrototypeOf(Jason,Turtle);

“JS”in Jason;//true

现在我们可以透过Jason存取JS属性了,这是因为每当像Jason存取JS时,便会在物件原型里搜寻该属性,因为我们已经让Jason继承了Turtle让它成为其原型,所以可以存取Turtle的属性。

在JS中,物件原型是物件的内部属性,无法直接存取,所以会标示为[[Prototype]]。

那如果我们想要Jason也能存取Kai的属性,相信很多人会直接这样写:

Object.setPrototypeOf(Jason,Kai);

“JS”in Jason;//false

“Vue”in Jason;//true

Jason的确可以存取Kai的属性了,但同时Kai也取代了Turtle成为了它的原型(leafor)。

那我们该怎么做呢?我们前面有提到过「每个物件都有[[Prototype]]特性可以来来指定其原型。」,所以Turtle成为Jason原型后,也可以指定Kai当作其原型,这个行为称为「原型串链(prototype chain)」。

Object.setPrototypeOf(Jason,Turtle);

Object.setPrototypeOf(Turtle,Kai);

“JS”in Jason;//true

“Vue”in Jason;//true

可以看到说Jason已经可以顺利存取Turtle及Kai的属性了!

那么,今天就到这边,一样如果有错误及来源未附上也欢迎留言指正,那么我们明天见。

05-11 13:43