1. 程式人生 > >學JS的心路歷程-物件與原型(一)

學JS的心路歷程-物件與原型(一)

前兩天說明面向物件的三大特性及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的屬性了!

 


那麼,今天就到這邊,一樣如果有錯誤及來源未附上也歡迎留言指正,那麼我們明天見。