前言
以前剛接觸到陣列map的時候,覺得很開心不用一直寫for迴圈,但我師父問起:你知道怎麼會有這個嗎?
然後就開始解釋起原型鏈這可怕的東西了…
在這裡只會提到原型繼承的概念,並不會挖太深。
1 | var arr = [1,2,3]; |
不只是map,還有許多方便的方法,在建立物件的時候,就跟著繼承下來了
函式建構子 Function constructor
從建立一個物件開始吧!
如果我今天要建造一個人?
1 | var person = { |
用物件實體法
也是最主流的方式,宣告一個人很酷的人做Roman。
但如果今天我需要快速得到很多不同名字的人呢?
函式回傳物件
1 | function getPerson (name, description) { |
目前為止沒什麼問題,但有點囉嗦。如果早知道要建立物件的話,又何必要建立新物件再回傳呢?也為了往後其他目的,JavaScript 透過函式建構子提供了方便的捷徑。
函式建構子
1 | function Person (name, description) { |
函式建構子名稱往往以大寫起頭,可方便你在程式碼中找出函式建構子或誤用。
一個是呼叫執行函式並將結果指向變數roman,一個是用new建立物件並指向變數roman;
當使用new時背後發生什麼事 ?
- JS直譯器
syantax parsor
會先建立一個空物件{}。 - 接著呼叫new後面的函式建構子,當函式被呼叫時,創造函式執行環境
Excusion
content
,this
關鍵字也隨之被創造出來。 - 由於
this
被寫在new
的後面,JS直譯器知道你在用函式建構子
創造物件,因此this
指向了剛被創造出來的空物件{},所以函式建構子
內的this.xxx
被創造在這個空物件中。
new會改變this的對象(原指向全域物件)
在函式建構子中 return
1 | function Person (name, description) { |
回傳字串不會受影響
1 | function Person (name, description) { |
回傳物件會把創立的新物件覆蓋掉
別忘記new
若使用使用函數建構子不用new,就會變成一般的呼叫函式。
1 | var roman = new Person('Roman', 'Cool'); |
Prototype 原型
重複用的函式
1 | function Person (name, description) { |
我加了一個打招呼的方法,在新創建的物件都使用這個方法
假設每個新創立的物件都會用到greeting
從圖中可以看到,看起來是同樣的函示,但事實是greeting分別存在兩個新建立的物件。
說明如果我建立10個新物件,就會多10個存放greeting的空間。
如果不是每個新物件都需要用到,就等於某些物件多建立了
greeting
浪費空間耗能。
放在工具包(繼承)
1 | function Person (name, description) { |
Person
的prototype
屬性,可以把它想成是Person
的工具包,每個function都有的屬性,被創立出來時是空的,可以使用prototype
幫這個物件(工具包)擴充。
而用new
創建新的Person
時,會把它繼承過去,物件本體雖然沒有這個greeting
,但沿著工具包找是可以取用到的。
兩個物件的
greeting
都指向同一個參考物件,記憶體上是同一個
所以說那個map呢?
有了剛剛那些概念,現在談談當我們宣告一個陣列時,發生的事情
1 | var arr = [1,2,3]; |
當我今天宣告一個陣列時,其實就把當使用new時背後發生什麼事 ?
提到的事情做完了
1 | var arr = [1,2,3]; |
- 宣告創造一個新的空陣列物件
- 將建構子的this指向過去
- 把工具包也傳承下去(但不存在陣列本體)
所以就有了開頭這張圖
陣列也算是物件的一種’
驗證
關鍵字:coercion強制轉型
小結
這篇本來是想把原型的都寫完,但秉持著每篇文章儘可能淺顯易懂,儘可能不要有太多的延伸討論,不要偏離標題太多,先簡述概念,之後在陸續把原型的理論補齊。
參考資料
[Peter Chang: Javascripter 必須知道的繼承 prototype, [[prototype]], __ proto __](https://peter-chang.medium.com/javascripter-必須知道的繼承因子-prototype-prototype-proto-object-class-inheritace-nodejs-物件-繼承-54102240a8b4)
Max’s Blog: 面試官最愛考的 JS 原型鏈
SimonAllen: 古典與原型繼承、瞭解原型
MDN: 繼承與原型鏈
Summer: 你懂 JavaScript 嗎?#19 原型(Prototype)
huli: 該來理解 JavaScript 的原型鍊了
[筆記] 談談 JavaScript 中的 function constructor 和關鍵字 new
MDN: 初學者應知道的物件導向 JavaScript