iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0
自我挑戰組

JavaScript 奇奇怪怪的核心觀念系列 第 18

(Day18) 原型特性與繼承

  • 分享至 

  • xImage
  •  

什麼是原型?

JavaScript 這個語言有一個特性,所以資料其實都是以『物件』方式做建立,因此也可以說 JavaScript 所有資料都有原型,而到底什麼是原型?

單純用文字比喻的話,原型其實像是藍圖,我們可以在原型設定各種屬性、方法,用來幫助我們建立實體資料,而實體資料則會帶者原型上的屬性以及方法,以下面圖片為例:

上述圖片只是幫助思考『原型的概念』而已,實際程式碼來說的話,我們會使用函示建構式、ES6 的 Class 來當作衣服的原型,而實體資料則是:

const blackT = {
	color:'black',
	material:'棉',
	size:'L'
}
const darkBlueT = {
	color:'darkBlue ',
	material:'聚酯纖維',
	size:'XL'
} 

這章節還不會講到如何建立原型,不過我們先將 blackT 物件丟到 console 並且再次呼叫,會顯示剛剛建立的 blackT 物件,不過物件的屬性底下還會有 [[Prototype]] 的東西,而這個 [[Prototype]] 其實就是今天介紹的原型。

值得一提的是原型本身還可以再繼承原型,因此這樣一段一段,因此又被稱做原型鍊,繼續使用衣服圖做範例:

P.S 過去文章會寫做 __proto__ 而不是 [[Prototype]] ,這是因為 JavaScript 這語言本來就有對每筆資料設置 [[prototype]] ,ES5 之前並沒有標準方法來查詢這個隱藏屬性,因此瀏覽器使用 __proto__ 這個方法來達成相關需求。

現在因為瀏覽器更新,所以 __proto__ 改為正式的 [[Prototype]] 不過實際上還是可以使用 __proto__ 等等相關方法,以上方 blackT 為例,使用 console.log(blackT.__proto__) 仍可以查到他的相關原型。

原型的特性

以下是原型的特性:

  • 一樣具有物件的特性
  • 向上查找特性
  • 原型可共用方法與屬性

這邊直接使用程式碼舉例比較好懂

const array = [1,2,3]
console.log(array) 

這邊的 array 就是個實體,點開 console 上的 array 裡面的 [[Prototype]] 就是原型,這點上面有提到。

而 array 中的 [[Prototype]] 有著許多我們常用的 陣列方法,比如 forEach()filter() ,這些方法正是透過原型繼承來的方法,這也提到一個重點:『若實體要取用原型中的方法,便是使用 . 這個運算子來使用』,這個重點也和上面提到的 『一樣具有物件的特性』是相同的。

眼尖的朋友就會發現在 forEachfilter 這些方法底下,還有一層 [[Prototype]] ,這正是上面提到的,原型上還有原型,同時也是『原型向上查找的特性』,同時不管是陣列、還是函示在最上層的原型都會是物件。

接下來可以驗證一下「原型的方法與屬性是共用的」這一點

const array = [1,2,3]

array.__proto__.dobuleNum= function() {
	return this.map(function(item) {
	return item*2})
}
console.log(array.dobuleNum()) //[2, 4, 6]

範例中使用 __proto__ 來新增 dobuleNum 這個方法,而 dobuleNum 就是將陣列中的值 *2 在回傳。透過 console.log(array.dobuleNum()) 也會確實看到回傳 [2,4,6] 的值。

接者我們在新增一個陣列變數來試試看上面觀念是否正確。

const newArray = [55,66,77]
console.log(newArray .dobuleNum()) //[110, 132, 154]

最後這邊要提醒一下,實做中是不建議使用 __proto__ 來製作原型方法,主要是這方法會污染所有原型,並讓原型來源難以查找、確認,比較實際的方法是使用原型的建構式,這寫是下一章節的主題。

參考文獻


上一篇
(Day17) this 介紹下 - 綁定 this 的 call & apply & bind 與嚴格模式
下一篇
(Day 19) 原型與建構式
系列文
JavaScript 奇奇怪怪的核心觀念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言