如何建立物件

如何建立物件?|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」關鍵字,電腦會預設去抓取原本就存在於電腦的「全域物件」。

未使用 new 時,電腦會預設選用全域物件

這樣會導致 this 關鍵字,將建構子函式模板中的成員,與全域物件連結再一起。

由於全域物件影響的範圍是整份 JS 檔案,這樣會導致後續程式碼混亂,也容易出現意想不到的狀況。

未使用 new 時,電腦會將建構子函式的內容,與全域物件綁定

因此,我們需要使用「new」關鍵字,建立一個新的空物件。

使用 new 創立新的物件

這樣與 this 關鍵字結合使用時,就能創立一個正常無疑慮的物件。

使用 new 時,電腦會將建構子函式的內容,與新建立的物件綁定

補充:因為使用 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 語法年代已久,因此衍生出各種語法。

希望大家可以藉由以上簡介,對於這些方式都有基礎理解。

Similar Posts