在前面的章節(jié)中,我們認(rèn)識了 map.keys(),map.values() 和 map.entries() 方法。
這些方法是通用的,有一個(gè)共同的約定來將它們用于各種數(shù)據(jù)結(jié)構(gòu)。如果我們創(chuàng)建一個(gè)我們自己的數(shù)據(jù)結(jié)構(gòu),我們也應(yīng)該實(shí)現(xiàn)這些方法。
它們支持:
MapSet-
Array
普通對象也支持類似的方法,但是語法上有一些不同。
Object.keys, values, entries
對于普通對象,下列這方法是可用的:
-
Object.keys(obj)—— 返回一個(gè)包含該對象所有的鍵的數(shù)組。 -
Object.values(obj)—— 返回一個(gè)包含該對象所有的值的數(shù)組。 -
Object.entries(obj)—— 返回一個(gè)包含該對象所有 [key, value] 鍵值對的數(shù)組。
......但是請注意區(qū)別(比如說跟 map 的區(qū)別):
第一個(gè)區(qū)別是,對于對象我們使用的調(diào)用語法是
Object.keys(obj),而不是obj.keys()。
為什么會這樣?主要原因是靈活性。請記住,在 Javascript 中,對象是所有復(fù)雜結(jié)構(gòu)的基礎(chǔ)。因此,我們可能有一個(gè)自己創(chuàng)建的對象,比如data,并實(shí)現(xiàn)了它自己的data.values()方法。同時(shí),我們依然可以對它調(diào)用Object.values(data)方法。第一個(gè)區(qū)別是
object.*方法返回的是“真正的”數(shù)組對象,而不只是一個(gè)可迭代項(xiàng)。這主要是歷史原因。
舉個(gè)例子:
let user = {
name: "John",
age: 30
};
Object.keys(user) = ["name", "age"]- `Object.values(user) = ["John", 30]
- `Object.entries(user) = [ ["name","John"], ["age", 30] ]
這里有一個(gè)使用 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 類型的鍵,那么這兒有一個(gè)單獨(dú)的方法 Object.getOwnPropertySymbols,它會返回一個(gè)只包含 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)會成對象。
例如,我們有一個(gè)帶有價(jià)格的對象,并想將它們加倍:
let prices = {
banana: 1,
orange: 2,
meat: 4,
};
let doublePrices = object.fromEntries(
//將價(jià)格轉(zhuǎn)換為數(shù)組,將每個(gè)鍵/值對映射為另一對
//然后通過 fromEntries 再將結(jié)果轉(zhuǎn)換為對象
Object.entries(prices).map(entry => [entry[0], entry[1] * 2])
);
alert(doublePrices.meat); //8