Javascript Object.keys,values,entries

2023-02-17 10:49 更新

對各個數(shù)據(jù)結(jié)構(gòu)的學(xué)習(xí)至此告一段落,下面讓我們討論一下如何迭代它們。

在前面的章節(jié)中,我們認(rèn)識了 map.keys(),map.values() 和 map.entries() 方法。

這些方法是通用的,有一個共同的約定來將它們用于各種數(shù)據(jù)結(jié)構(gòu)。如果我們創(chuàng)建一個我們自己的數(shù)據(jù)結(jié)構(gòu),我們也應(yīng)該實現(xiàn)這些方法。

它們支持:

  • ?Map?
  • ?Set?
  • ?Array?

普通對象也支持類似的方法,但是語法上有一些不同。

Object.keys,values,entries

對于普通對象,下列這些方法是可用的:

  • Object.keys(obj) —— 返回一個包含該對象所有的鍵的數(shù)組。
  • Object.values(obj) —— 返回一個包含該對象所有的值的數(shù)組。
  • Object.entries(obj) —— 返回一個包含該對象所有 [key, value] 鍵值對的數(shù)組。

……但是請注意區(qū)別(比如說跟 map 的區(qū)別):

Map Object
調(diào)用語法 map.keys() Object.keys(obj),而不是 obj.keys()
返回值 可迭代對象 “真正的”數(shù)組

第一個區(qū)別是,對于對象我們使用的調(diào)用語法是 Object.keys(obj),而不是 obj.keys()。

為什么會這樣?主要原因是靈活性。請記住,在 JavaScript 中,對象是所有復(fù)雜結(jié)構(gòu)的基礎(chǔ)。因此,我們可能有一個自己創(chuàng)建的對象,比如 data,并實現(xiàn)了它自己的 data.values() 方法。同時,我們依然可以對它調(diào)用 Object.values(data) 方法。

第二個區(qū)別是 Object.* 方法返回的是“真正的”數(shù)組對象,而不只是一個可迭代對象。這主要是歷史原因。

舉個例子:

let user = {
  name: "John",
  age: 30
};
  • ?Object.keys(user) = ["name", "age"]?
  • ?Object.values(user) = ["John", 30]?
  • ?Object.entries(user) = [ ["name","John"], ["age",30] ]?

這里有一個使用 ?Object.values? 來遍歷屬性值的例子:

let user = {
  name: "John",
  age: 30
};

// 遍歷所有的值
for (let value of Object.values(user)) {
  alert(value); // John, then 30
}

Object.keys/values/entries 會忽略 symbol 屬性

就像 for..in 循環(huán)一樣,這些方法會忽略使用 Symbol(...) 作為鍵的屬性。

通常這很方便。但是,如果我們也想要 Symbol 類型的鍵,那么這兒有一個單獨的方法 Object.getOwnPropertySymbols,它會返回一個只包含 Symbol 類型的鍵的數(shù)組。另外,還有一種方法  Reflect.ownKeys(obj),它會返回 所有 鍵。

轉(zhuǎn)換對象

對象缺少數(shù)組存在的許多方法,例如 map 和 filter 等。

如果我們想應(yīng)用它們,那么我們可以使用 Object.entries,然后使用 Object.fromEntries

  1. 使用 ?Object.entries(obj)? 從 ?obj? 獲取由鍵/值對組成的數(shù)組。
  2. 對該數(shù)組使用數(shù)組方法,例如 ?map?,對這些鍵/值對進(jìn)行轉(zhuǎn)換。
  3. 對結(jié)果數(shù)組使用 ?Object.fromEntries(array)? 方法,將結(jié)果轉(zhuǎn)回成對象。

例如,我們有一個帶有價格的對象,并想將它們加倍:

let prices = {
  banana: 1,
  orange: 2,
  meat: 4,
};

let doublePrices = Object.fromEntries(
  // 將價格轉(zhuǎn)換為數(shù)組,將每個鍵/值對映射為另一對
  // 然后通過 fromEntries 再將結(jié)果轉(zhuǎn)換為對象
  Object.entries(prices).map(entry => [entry[0], entry[1] * 2])
);

alert(doublePrices.meat); // 8

乍一看,可能感覺有點困難,但是使用一兩次之后就很容易理解了。我們可以通過這種方式建立強(qiáng)大的轉(zhuǎn)換鏈。

任務(wù)


屬性求和

重要程度: 5

有一個帶有任意數(shù)量薪水的 salaries 對象。

編寫函數(shù) sumSalaries(salaries),該函數(shù)使用 Object.values 和 for..of 循環(huán)返回所有薪水的總和。

如果 salaries 是空對象,那么結(jié)果必須是 0。

舉個例子:

let salaries = {
  "John": 100,
  "Pete": 300,
  "Mary": 250
};

alert( sumSalaries(salaries) ); // 650

解決方案

function sumSalaries(salaries) {

  let sum = 0;
  for (let salary of Object.values(salaries)) {
    sum += salary;
  }

  return sum; // 650
}

let salaries = {
  "John": 100,
  "Pete": 300,
  "Mary": 250
};

alert( sumSalaries(salaries) ); // 650

還有另外一種可選方案,即使用 Object.values 和 reduce 來求和:

// 使用 reduce 方法遍歷 salaries 數(shù)組
// 把它們加起來
// 返回最終結(jié)果
function sumSalaries(salaries) {
  return Object.values(salaries).reduce((a, b) => a + b, 0) // 650
}

計算屬性數(shù)量

重要程度: 5

寫一個函數(shù) ?count(obj)?,該函數(shù)返回對象中的屬性的數(shù)量:

let user = {
  name: 'John',
  age: 30
};

alert( count(user) ); // 2

試著使代碼盡可能簡短。

P.S. 忽略 Symbol 類型屬性,只計算“常規(guī)”屬性。


解決方案

function count(obj) {
  return Object.keys(obj).length;
}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號