本文 AI 產出,尚未審核

JavaScript 物件操作:Object.keysObject.valuesObject.entries


簡介

在 JavaScript 中,物件(Object)是最常用的資料結構之一。它以「鍵-值」的形式儲存資訊,讓我們可以隨時透過鍵名取得對應的值。雖然直接存取單一屬性相當簡單,但在實務開發中,我們常常需要遍歷整個物件取得所有鍵或值,甚至同時取得鍵和值來進行資料處理。

Object.keysObject.valuesObject.entries 正是為了這些需求而設計的三個靜態方法。它們不僅讓程式碼更具可讀性,也能避免手動寫迴圈時可能產生的錯誤。掌握這三個方法,等於掌握了物件資料的「全景視角」,在資料轉換、表單處理、API 回傳結果的解析等情境中,都能大幅提升開發效率。


核心概念

1. Object.keys(obj)

  • 功能:回傳一個陣列,裡面包含物件自身(不含原型鏈)所有可列舉(enumerable)的鍵(屬性名稱)。
  • 回傳值類型Array<string>
  • 常見用途:遍歷鍵、計算屬性數量、配合 Array.prototype.map 產生新資料結構。
const user = {
  name: "Alice",
  age: 28,
  email: "alice@example.com"
};

const keys = Object.keys(user);
console.log(keys); // ["name", "age", "email"]

Object.keys 只會列出可列舉的自有屬性,Symbol 型別的鍵不會被包含。


2. Object.values(obj)

  • 功能:回傳一個陣列,裡面包含物件自身所有可列舉屬性的
  • 回傳值類型Array<any>
  • 常見用途:快速取得所有值進行統計、過濾或映射(map)等操作。
const scores = {
  math: 92,
  english: 85,
  science: 78
};

const values = Object.values(scores);
console.log(values); // [92, 85, 78]

// 計算平均分數
const avg = values.reduce((sum, v) => sum + v, 0) / values.length;
console.log(`平均分數:${avg}`); // 平均分數:85

3. Object.entries(obj)

  • 功能:回傳一個二維陣列,每個子陣列都是 [key, value] 形式,代表一組鍵值對。
  • 回傳值類型Array<[string, any]>
  • 常見用途:同時需要鍵與值時的遍歷、Map 轉換、物件排序等。
const product = {
  id: "A001",
  name: "筆記型電腦",
  price: 29999
};

const entries = Object.entries(product);
console.log(entries);
// [["id","A001"], ["name","筆記型電腦"], ["price",29999]]

// 轉成 Map 物件
const productMap = new Map(entries);
console.log(productMap.get("price")); // 29999

4. 為什麼要使用這三個方法?

情境 手寫 for...in Object.keys/values/entries
只要鍵 for (let k in obj) { if (obj.hasOwnProperty(k)) … } Object.keys(obj).forEach(k => …)
只要值 需要再取一次 obj[k] Object.values(obj).forEach(v => …)
同時需要鍵和值 兩層取得 Object.entries(obj).forEach(([k,v]) => …)
可鏈式操作 不易 支援 mapfilterreduce 等陣列方法

使用這三個靜態方法,程式碼更簡潔、可讀性更高,且自動過濾掉原型鏈上的屬性,降低錯誤機率。


程式碼範例(實用 5 篇)

範例 1:把物件轉成查詢字串(Query String)

function toQueryString(obj) {
  // Object.entries 讓我們同時取得鍵和值
  return Object.entries(obj)
    .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
    .join('&');
}

const params = {
  search: "JavaScript 教學",
  page: 2,
  limit: 20
};

console.log(toQueryString(params));
// output: search=JavaScript%20%E6%95%99%E5%AD%B8&page=2&limit=20

重點:使用 Object.entries 可以一次取得鍵和值,配合 Array.prototype.map 完成資料映射。


範例 2:過濾出物件中「真值」的屬性

function filterTruthy(obj) {
  // 先拿到鍵,再過濾值為 falsy 的項目
  return Object.keys(obj)
    .filter(key => Boolean(obj[key]))
    .reduce((acc, key) => {
      acc[key] = obj[key];
      return acc;
    }, {});
}

const raw = {
  name: "Bob",
  age: 0,        // falsy, 會被過濾掉
  email: "",     // falsy
  active: true
};

console.log(filterTruthy(raw)); // { name: "Bob", active: true }

說明Object.keys 搭配 filterreduce,可以快速產生「淨化」後的物件。


範例 3:將物件的值平方後回傳新物件

function squareValues(obj) {
  // 使用 Object.entries 直接取得鍵和值,map 後再轉回物件
  const squared = Object.entries(obj).map(
    ([k, v]) => [k, typeof v === "number" ? v * v : v]
  );
  return Object.fromEntries(squared);
}

const numbers = { a: 2, b: 5, c: "hello", d: 10 };
console.log(squareValues(numbers));
// { a: 4, b: 25, c: "hello", d: 100 }

技巧Object.fromEntries(ES2019)可以把 [[k,v], …] 直接變回物件,寫法非常簡潔。


範例 4:依照物件值排序(從大到小)

function sortByValueDesc(obj) {
  // 先取得 entries,依值排序,再轉回物件
  const sorted = Object.entries(obj)
    .sort(([, v1], [, v2]) => v2 - v1); // v2 - v1 => 降序
  return Object.fromEntries(sorted);
}

const scores = { alice: 88, bob: 95, carol: 72 };
console.log(sortByValueDesc(scores));
// { bob: 95, alice: 88, carol: 72 }

應用:排行榜、統計圖表的資料前處理。


範例 5:深層遍歷物件的所有鍵(遞迴版)

function deepKeys(obj, prefix = '') {
  let result = [];
  for (const [key, value] of Object.entries(obj)) {
    const fullKey = prefix ? `${prefix}.${key}` : key;
    result.push(fullKey);
    if (value && typeof value === 'object' && !Array.isArray(value)) {
      // 只對純物件遞迴
      result = result.concat(deepKeys(value, fullKey));
    }
  }
  return result;
}

const nested = {
  user: {
    name: "Eve",
    address: {
      city: "Taipei",
      zip: "106"
    }
  },
  active: true
};

console.log(deepKeys(nested));
// [
//   "user", "user.name", "user.address",
//   "user.address.city", "user.address.zip", "active"
// ]

說明:即使是多層結構,仍能利用 Object.entries 取得鍵和值,再遞迴產生「完整路徑」的鍵名。


常見陷阱與最佳實踐

陷阱 說明 解決方式
原型鏈屬性被遍歷 使用 for...in 時會列出原型上的屬性 改用 Object.keys/values/entries,或在 for...in 中加 obj.hasOwnProperty(key)
Symbol 鍵不會被列出 三個方法只處理字串鍵 若需包含 Symbol,使用 Object.getOwnPropertySymbols 再自行合併
排序會改變原始物件順序 物件本身是無序集合,排序後必須重新產生新物件 使用 Object.entriessortObject.fromEntries,避免直接改變原物件
Object.values 回傳的陣列是 「引用」 還是「值」 若值是物件,陣列中的元素仍指向同一個參考 若需要深拷貝,使用 JSON.parse(JSON.stringify(...))structuredClone
使用舊版瀏覽器不支援 Object.entriesObject.fromEntries 在 IE 不支援 透過 Babel/polyfill 或改用 Object.keys + reduce 的方式實作

最佳實踐

  1. 盡量使用 Object.entries:同時需要鍵和值時,它是最直觀的選擇。
  2. 結合陣列方法mapfilterreduce 能讓資料轉換一次搞定,避免多層迴圈。
  3. 保持不可變性:在函式式編程風格下,使用 Object.fromEntries 產生新物件,避免直接變更原始資料。
  4. 考慮 enumerable 屬性:若屬性被設定為 enumerable: false,上述三個方法不會列出,必要時使用 Object.getOwnPropertyNames
  5. 使用 TypeScript 時加上型別Object.entries<T>(obj) 能保留鍵值型別,提升編譯期安全。

實際應用場景

  1. 表單資料序列化
    前端送出表單時,常把物件轉成 URL query string。Object.entries 搭配 map 能快速完成編碼與串接。

  2. API 回傳資料的過濾與映射
    從後端取得的 JSON 可能包含許多不必要欄位,使用 Object.keysObject.entries 可以只保留需要的屬性,減少前端的資料負擔。

  3. 動態產生 UI 列表
    例如根據權限物件 ({ read: true, write: false, admin: true }) 產生對應的功能按鈕。Object.entries 可直接遍歷鍵和值,判斷是否顯示。

  4. 資料統計與報表
    Object.values 讓我們能輕鬆計算總和、平均、最大最小值,常用於儀表板或圖表的前處理。

  5. 資料結構轉換
    把普通物件轉成 MapSetWeakMap 等結構,或相反方向的轉換,都離不開 Object.entries


總結

  • Object.keysObject.valuesObject.entries遍歷與操作物件的核心工具,它們把「鍵」與「值」抽象成陣列,使我們能利用完整的陣列 API 進行映射、過濾、排序與聚合。
  • 使用這三個方法可以避免 for...in 帶來的原型鏈問題、手動檢查 hasOwnProperty 的繁瑣,讓程式碼更簡潔、可讀且安全
  • 結合 Object.fromEntriesArray.prototype 方法以及 ES6+ 的解構賦值,我們可以在 保持不可變性的同時 完成複雜的資料轉換與處理。
  • 在實務開發中,從表單序列化、API 回傳資料的淨化、動態 UI 產生,到統計分析與結構轉換,這三個方法都是不可或缺的好幫手。

掌握 Object.keys / values / entries,就等於掌握了 物件資料的全方位操作能力,在日常開發與大型專案中,都能為你節省大量時間與降低錯誤率。祝你寫程式愉快,持續探索 JavaScript 的無限可能!