如何建立物件?|JavaScript 初學者筆記(2)
更新日期: 2023 年 3 月 1 日
我在學習 JavaScript 物件時,最困擾自己的一件事就是有太多不同的語法,其實在做一樣的事情。
若是從現在的時間點切入,對於這個現象會難以理解,但我們將時間的間距拉長,就會發現其實一切都是有跡可循。
因為 JavaScript 經歷過數十年的演變,過程中經過不斷改良與優化,因此不斷衍生出新語法與編程技術。
本文,就是要針對「建立物件」的 3 種相關語法簡介,幫助各位釐清思緒。
建議閱讀本文前,可以先理解一下 JavaScript 物件導向程式設計相關觀念,會有更深刻的體悟。
(學習建議:在開始學習之前可以先聽一首歌,邊聽邊學成效更佳👍)
物件實體語法(Object Literal Syntax)
建立物件的第一個方式,是使用「物件實體語法」。
我們只要先宣告一個變數,並且撰寫一對尖括弧「{ }」,即可順利創立一個空白物件。
let jojo = {};
物件是由「鍵」(key) 與「值」(value) 組成。
你可以將「鍵」想像成某個資料的名稱,「值」則為該資料的實際數據,以人這個物件來說:
- 體重(key):84 公斤(value)
- 身高(key):180 公分(value)
- 姓名(key):徐培鈞(value)
套用到程式碼中,我們需要將該物件的數據放進尖括號中,並且以「,」分隔每一對「鍵值」的數據。
特別注意,在新增第二對鍵值時,一定要放上英文的逗號,才能順利建立完成歐。
例如若我們想要創立一個第五代 JoJo 的物件,程式碼會成以下形式:
let jojo5 = {
fullname: '喬魯諾·喬巴拿',
age: 15,
stand: '黃金體驗'
};
除了一般的數值,我們也可以在「值」(value)的部分放「函式」。
一般來說,當我們在物件的值放入函式時,會以函式表達式(Function Expression)呈現。
如果不知道「函式表達式」是啥東東的人,可以看一下連結內的文章。
let jojo5 = {
fullname: '喬魯諾·喬巴拿',
age: 15,
stand: '黃金體驗',
say: function(){
console.log('我喬魯諾喬巴拿有個偉大的夢想,那就是成為流氓巨星!');
}
};
另外 ES6 (2018 年的 JavaScript 版本)針對物件內的函式,也提供了新的寫法。
兩者功能都相同,只是撰寫方式不同而已,沒有優劣之分。
let jojo5 = {
say: function(){
console.log('我喬魯諾喬巴拿有個偉大的夢想,那就是成為流氓巨星!');
} // 第 1 種寫法
say(){
console.log('我喬魯諾喬巴拿有個偉大的夢想,那就是成為流氓巨星!');
} // 第 2 種寫法
};
另外,除了函式外也可在物件中,另外再放入新的物件,就是俗稱的二維物件。
撰寫方式是在「:」後面再插入一對尖括號,表示創建一個新物件。
let jojo5 = {
fullname: '喬魯諾·喬巴拿',
age: 15,
stand: '黃金體驗',
say: function(){
console.log('我喬魯諾喬巴拿有個偉大的夢想,那就是成為流氓巨星!');
}
enemy: {
fullname: '迪亞波羅',
age: 34,
stand: '克里姆王'
}
};
我們會將物件內的元素,稱為「成員」(member)。
在這些成員中,又會將物件內的函式稱為「方法」(method)、其他非函式的成員稱為「屬性」(property)。
let jojo5 = {
fullname: '喬魯諾·喬巴拿', // 這是物件的成員之一,又稱為「屬性」
age: 15, // 這是物件的成員之一,又稱為「屬性」
stand: '黃金體驗', // 這是物件的成員之一,又稱為「屬性」
say: function(){
console.log('我喬魯諾喬巴拿有個偉大的夢想,那就是成為流氓巨星!');
}, // 這是物件的成員之一,又稱為「方法」
enemy: {
fullname: '迪亞波羅',
age: 34,
stand: '克里姆王'
} // 這是物件的成員之一,又稱為「屬性」
};
建立完物件後,我們可以使用「點」去取用物件內成員的值。
補充:點「.」在 JavaScript 是一種運算子,主要用來提取物件的成員。
具體來說,語法大約會以此形式呈現:物件名稱.物件成員名稱。
若該物件中又有另一個物件,則需要再「點」一次:外層物件名稱.內層物件名稱.物件成員名稱
jojo5.fullname //取用 jojo 的本名
jojo5.stand // 取用 jojo 替身的名稱
jojo5.enemy.age // 取用 jojo 敵人物件中,年齡的值
當你將這段程式碼打在編輯器中,可能無法正常顯示在網頁上,這是正常現象。
你需要搭配使用 console.log 此函式,才能正常顯示。
console.log(jojo5.fullname) // 顯示 jojo 的本名
console.log(jojo5.stand) // 顯示 jojo 替身的名稱
console.log(jojo5.enemy.age) // 顯示jojo 敵人物件中,年齡的值
如果你取用的成員是方法(也就是函式),你可以結合剛剛的點記法,在該方法名稱後加一對圓括號「( )」並搭配結尾符號「;」,即可順利執行該函式。
jojo5.say(); //使用 jojo 說話的函式
沒意外的話,此程式碼應該會在螢幕顯示喬魯諾的名言。👍
有些新手在學習時,會將 JSON 與上述所說的 Object Literal Syntax 搞混。
雖然這兩個語法外觀極為相似,但其實還是稍有不同,需要請各位初學者留意一下。
工廠函式(Factory function)
在方法一中,我們介紹了創立物件的基本方法:透過一對尖括號,並在其中插入每個物件「成員」的「鍵」與「值」。
這種方法的好處是直觀且易於理解,但壞處就是比較製作過程麻煩。
當我們今天要創立好幾個相近的成員時,就只能不斷使用「複製、貼上」大法,並逐一修改各元素成員的內容。
我們繼續以 JoJo 舉例,假如我想要以剛剛的方式再創立第六代 JoJo,就需要複製貼上一次,並修改其內容。
let jojo5 = {
fullname: '喬魯諾·喬巴拿',
age: 15,
stand: '黃金體驗',
say: function(){
console.log('我喬魯諾喬巴拿有個偉大的夢想,那就是成為流氓巨星!');
}
enemy: {
fullname: '迪亞波羅',
age: 34,
stand: '克里姆王'
}
};
let jojo6 = {
fullname: '東方仗助',
age: 16,
stand: '瘋狂鑽石',
say: function(){
console.log('承太郎先生你在幹什麼?快用你那無敵的白金之星想想辦法啊!');
}
enemy: {
fullname: '吉良吉影',
age: 33,
stand: '殺手皇后'
}
};
為了提高製作物件的效率,並讓後續的代碼容易修改與維護,我們可以換另一方法創立物件:
先創立一個「公版物件」,其他新物件再套用此公版即可。
若要創立公版的物件,我們可以使用「工廠函式」或是「建構子」達成此要求。
首先,我們先介紹工廠函式(Factory function)的用法。
工廠函式簡單來說,就是一個函式。
只是這個函式回傳的數值,不再只是單純的文字與數字,而是一個「物件」。
例如若我們想創立一個創立 JoJo 的函式,他會程式碼慧如以下顯示。
除了一般的函式名稱,還需要增加「return」關鍵字,以及一對尖括號「{ }」表達該回傳值屬於一個物件。
function creatJojo(){
return {
}
};
接著,我們一樣在尖括號中放入所需要成員的「鍵」(key)名稱。
這裡注意,因為「鍵」所對應的「值」是一個不斷變動的數據,會根據每次創立的腳色不同,而有不同的內容。
因此,需要值的內容以函式中「參數」取代,方便其他人填入對應的資料。
為了顯示方便,通常我們會將「鍵」與函式中「參數」設成相同的名稱,方便後續代碼的查看與理解。
大家查看程式碼時,可以透過顏色區分該名稱屬於物件的「鍵名稱」,還是「參數名稱」。
- 紅色:鍵名稱
- 白色:參數名稱
function creatJojo(fullname,age,stand){
return {
fullname: fullname,
age: age,
stand: stand
}
};
在 ES6 中,也有針對工廠函式這種相同名稱的寫法,提供更簡便的寫法,大家可以參考看看。
從顏色可以看出,原本「鍵名稱」直接被「參數名稱」取代。
function creatJojo(fullname,age,stand){
return {
fullname,
age,
stand
}
};
在工廠函式除了可以放入中物件的「屬性」,也可以放入物件的「方法」。
這裡我們可以將 say 函數裡面的文字內容,新增一個 word 參數。
如此一來,使用者就可以藉由在使用工廠函式時,在 word 參數區塊根據不同的腳色,提供不同的台詞。
function creatJojo(fullname,age,stand,word){
return {
fullname: fullname,
age: age,
stand: stand,
say: function(){
console.log(word);
}
}
};
建立好工廠函式後,只要以正常函式的使用方法,就可以順利建立一個物件。
例如若想創立 jojo 5 的物件,只要寫出以下代碼即可順利完成。
// 創立 jojo5 的物件
let jojo5 = creatJojo('喬魯諾·喬巴拿','15','黃金體驗','我喬魯諾喬巴拿有個偉大的夢想,那就是成為流氓巨星!');
建構子函式(Constructor function)
最後,我們來說明一下第三種方法:建構子函式。
建構子函式本質上來說就只是一個函式,只是它的功能跟「工廠函式」一樣,都是專門用來「建立物件」
差別在於,建構子函式不使用 「return」,而是使用了「this」與「new」這兩個關鍵字。
首先,我們先創立一個函數,並且將該函命名稱的開頭大寫,用來表示它是建構子函式。
建構子函式的名稱開頭要大寫,只是一種約定成俗的程式碼命名方式,沒有特別意涵。
function CreatJojo(){
};
接著,我們可以在該函式中放入「this」關鍵字,用來代替稱呼要新建的物件。
我們可以將它想成一個替代稱呼的名稱:
物件.成員 //正常使用物件
this.成員 //以 this 取代
你可能會問,為什麼不直接使用該物件的名稱就好,還要拐彎抹角使用 this 此關鍵字。
原因在於,我們根本還沒創立該物件。因此要先用一個 this 預設值,指向未來該物件的位子。
等到那個物件被我們創立後,我們就能 this 表示該物件的名稱,創立一個真正的物件。
因為我們需要將資料寫入該物件成員中,因此除了「this」還需要加入等號「=」才算完成。
// 工廠函式:給成員資料
成員1: 資料1,
成員2: 資料2
// 建構子函式:給成員資料
this.成員1 = 資料1;
this.成員2 = 資料2;
再搭配函數的參數,實際的程式碼會長成以下樣子:
function CreatJojo(fullname,age,stand,word){
this.fullname = fullname ;
this.age = age ;
this.stand = stand ;
this.say = function(){
console.log(word) ;
};
};
上述代碼,已經幫我們創立好一個 JOJO 角色模板,接著需要實際使用此函數,才能成功建立物件。
假如我們想要創立五代 JOJO,實際使用方法為以下:
let jojo5 = new CreatJojo('喬魯諾·喬巴拿','15','黃金體驗','我喬魯諾喬巴拿有個偉大的夢想,那就是成為流氓巨星!');
從這段程式碼中你可以發現,它與正常引用函數不同,還有多一個「new」關鍵字。
原因在於,如果沒有使用「new」關鍵字,電腦會預設去抓取原本就存在於電腦的「全域物件」。
這樣會導致 this 關鍵字,將建構子函式模板中的成員,與全域物件連結再一起。
由於全域物件影響的範圍是整份 JS 檔案,這樣會導致後續程式碼混亂,也容易出現意想不到的狀況。
因此,我們需要使用「new」關鍵字,建立一個新的空物件。
這樣與 this 關鍵字結合使用時,就能創立一個正常無疑慮的物件。
補充:因為使用 new 關鍵字時,電腦會自動創立一個新的物件。
因此我們在使用建構子函式時,不會在函式結尾添加「return」關鍵字,會多此一舉。
function CreatJojo(fullname,age,stand,word){
this.fullname = fullname ;
this.age = age ;
this.stand = stand ;
this.say = function(){
console.log(word);
};
return this // 不會寫這一行文字!!
};
結論
以上就是建立物件的 3 種方式,包含了「物件實體語法」、「工廠函式」、「建構子函式」。
回過頭來看,會出現這麼多種方式就是因為 JS 語法年代已久,因此衍生出各種語法。
希望大家可以藉由以上簡介,對於這些方式都有基礎理解。
系列文章統整
- 物件導向是什麼?|JavaScript 四大物件特性簡介|初學者筆記(1)
- 如何建立物件?|JavaScript 初學者筆記(2)
- 什麼是原型(Prototype)?|JavaScript 初學者筆記(3)
- 類別(class)是什麼?|JavaScript 初學者筆記(4)