物件

物件 在 JavaScript

18 個練習

關於 物件

說明

除了像number和string這類基本資料型態之外,JavaScript 還有另一種重要的資料型態,叫做object。 物件是鍵值對的集合。 因此,它們可以當作其他語言中常說的映射或字典來使用。

在其他語言中,映射裡的所有值通常都必須是相同的資料型態。 在 JavaScript 中,只有鍵的型態受到限制:它必須是字串。 一個物件裡的值可以有各種不同的型態。 它們可以是數字這類基本型態,也可以是陣列、其他物件,甚至函式。 這讓物件非常有彈性,也因此成為 JavaScript 中物件導向程式設計(OOP)的核心要角。

接下來,我們會聚焦在物件作為集合或映射的用途。物件的其他用法會在其他概念中介紹,例如類別。

建立物件

你可以用大括號建立物件實字。 你也可以直接在裡面加入一些項目(鍵值對)。 做法是先寫鍵,接著是冒號,然後是值。

const emptyObject = {};

const obj = {
  favoriteNumber: 42,
  greeting: 'Hello World',
  useGreeting: true,
  address: {
    street: 'Trincomalee Highway',
    city: 'Batticaloa',
  },
  fruits: ['melon', 'papaya'],
  addNumbers: function (a, b) {
    return a + b;
  },
};

在 JavaScript 中,最後一個項目後面的尾逗號是可有可無的。 你可以在這裡讀到使用它的好處。

你可能會納悶,鍵明明應該是字串,為什麼不用加上引號。 這是一種簡寫法。 如果鍵符合 JavaScript 識別字的命名規則,就可以省略引號。 如果鍵的名稱含有特殊字元,就得使用一般的字串寫法。

const obj = {
  '1keyStartsWithNumber': '...',
  'key/with/slashes': '...',
  'key-with-dashes': '...',
  'key with spaces': '...',
  '#&()[]{}èä樹keyWithSpecialChars': '...',
};

宣告物件時,你可能常會想加入一些現有的變數。 這往往會寫出name: name這樣的鍵值對。 JavaScript 有種簡寫法,讓你只要寫name就好。 在物件裡定義函式也有簡寫法。 這樣就可以省略冒號和function關鍵字。

const x = 1;
const y = 2;

const obj = {
  x: x,
  y: y,
  calcSum: function (a, b) {
    return a + b;
  },
};

// Can be shortened to ...
const obj = {
  x,
  y,
  calcSum(a, b) {
    return a + b;
  },
};

如果你想建立的物件實字,其鍵名存放在變數中,或是由運算式算出來的,就需要把變數或運算式用方括號包起來。

const key = 'greeting';

const obj = {
  [key]: 'hello world',
};
console.log(obj);
// => { greeting: 'hello world' }

取得值

要取得某個鍵對應的值有兩種方式:點記法和括號記法。

const obj = { greeting: 'hello world' };

obj.greeting;
// => hello world

obj['greeting'];
// => hello world

// Bracket notation also works with variables.
const key = 'greeting';
obj[key];
// => hello world

使用點記法這個簡寫,和省略引號有一樣的限制。 只有在鍵符合識別字命名規則時才能用。

如果你想取得的鍵不存在於物件中,JavaScript 會回傳undefined。 關於這點的更多細節,請參考 Null 與 Undefined。

如果想從巢狀物件中取得值,可以把鍵串接起來。

const obj = {
  address: {
    street: 'Trincomalee Highway',
    city: 'Batticaloa',
  },
};

obj.address.city;
// => 'Batticaloa'

obj['address']['city'];
// => 'Batticaloa'

// Notations can also be mixed.
obj.address['city'];
// => 'Batticaloa'

新增或修改值

你可以用賦值運算子=來新增或修改值。 同樣地,點記法和括號記法都可以用。

const obj = { greeting: 'hello world' };

obj.greeting = 'Hi there!';
obj['greeting'] = 'Welcome.';

obj.newKey1 = 'new value 1';
obj['new key 2'] = 'new value 2';

const key = 'new key 3';
obj[key] = 'new value 3';

刪除項目

你可以用delete關鍵字從物件中刪除鍵值對。

const obj = {
  key1: 'value1',
  key2: 'value2',
};

delete obj.key1;
delete obj['key2'];

要注意的是,雖然取得不存在的鍵會回傳undefined,但把某個鍵設成undefined並不會移除這個項目。 請一律改用delete。

檢查鍵是否存在

你可以用hasOwnProperty方法檢查某個鍵是否存在於物件中。

const obj = { greeting: 'hello world' };

obj.hasOwnProperty('greeting');
// => true

obj.hasOwnProperty('age');
// => false

對於繼承而來的鍵,hasOwnProperty會回傳false。這通常正是你想要的行為。 如果你想把繼承而來的鍵也納入檢查,可以改用 in 運算子。

走訪物件

有一種特別的for...in迴圈,可以疊代物件中所有的鍵。

const obj = {
  name: 'Ali',
  age: 65,
};

for (let key in obj) {
  console.log(key, obj[key]);
}
// name Ali
// age 65

for...in看起來好像總是依照鍵出現或加入物件的順序(插入順序)來走訪。 不過,你不該依賴這點,因為在某些特殊情況下,順序會和插入順序不同。 寫程式時,請一律假設順序是任意的。 如果你需要可靠的順序,請改用 Map 或巢狀[陣列][concept-arrays],而不是物件。

如果物件有繼承而來的鍵,for…in迴圈就會有個陷阱。 那些鍵也會被for…in迴圈走訪。 你通常會想避免這種情況,所以得如下所示把它們跳過。

for (let key in obj) {
  if (!obj.hasOwnProperty(key)) {
    continue;
  }
  // ...
}

JavaScript 也有for...of迴圈,例如用來疊代陣列。 重要的是,for...in和for...of不能互換使用,詳情請參考 MDN 文件。

鍵、值與項目

內建的物件Object提供了一些輔助方法,可以把某個物件的所有鍵、值或項目以陣列形式取出。

const obj = {
  name: 'Ali',
  age: 65,
};

Object.keys(obj);
// => [ 'name', 'age' ]

Object.values(obj);
// => [ 'Ali', 65 ]

Object.entries(obj);
// => [ [ 'name', 'Ali' ], [ 'age', 65 ] ]

真正空無一物的物件

你可能已經注意到,JavaScript 裡的空物件並不是完全空的。 例如,它含有hasOwnProperty方法,以及toString這類其他方法。 這通常不會造成任何問題,但如果你真的需要建立一個完全空無一物的物件,可以使用 null 物件,它能透過Object.create(null)建立。

透過 GitHub 編輯 連結會在新視窗或分頁中開啟

學習 物件