javascript
js map对象遍历_何时使用 Map 来代替变通的 JS 对象
JS 普通對(duì)象 {key: 'value'} 用于存放結(jié)構(gòu)化數(shù)據(jù)。但有一件事我覺(jué)得很煩:對(duì)象鍵必須是字符串(或很少使用的 symbol)。
如果將數(shù)字用作鍵會(huì)怎樣?在這種情況下不會(huì)有錯(cuò)誤:
const?names?=?{??1:?'One',
??2:?'Two',
};
Object.keys(names);?//?=>?['1',?'2']
JS 會(huì)隱式地將對(duì)象的鍵轉(zhuǎn)換為字符串,這種默認(rèn)行為丟失了類(lèi)型的一致性,要解決也挺棘手的。但 ES6 中的Map 對(duì)象可以幫我們解決這類(lèi)的問(wèn)題,Look See See。
1. Map 接受任何類(lèi)型的鍵
如前所述,如果對(duì)象的鍵不是 string 或 symbol,JS 將隱式地將其轉(zhuǎn)換為字符串。
幸運(yùn)的是,map 的鍵類(lèi)型沒(méi)有問(wèn)題
const?numbersMap?=?new?Map();numbersMap.set(1,?'one');
numbersMap.set(2,?'two');
[...numbersMap.keys()];?//?=>?[1,?2]
1 和 2 是 numbersMap 中的鍵,這些鍵的類(lèi)型(數(shù)字)保持不變。
可以在 mpa 中使用任何鍵類(lèi)型:數(shù)字、布爾值、字符串和 symbol。
const?booleansMap?=?new?Map();booleansMap.set(true,?"Yep");
booleansMap.set(false,?"Nope");
[...booleansMap.keys()];?//?=>?[true,?false]
booleansMap 使用 booleans 作為鍵,沒(méi)有問(wèn)題。相反,布爾鍵在普通對(duì)象中不起作用。
來(lái)突破一下想象:是否將整個(gè)對(duì)象作為 map 的鍵,答案:可以的。
1.1 對(duì)象作為鍵
假設(shè)你需要存儲(chǔ)一些與對(duì)象相關(guān)的數(shù)據(jù),而不需要將這些數(shù)據(jù)附加到對(duì)象本身。使用普通對(duì)象是不可能的。
解決方法是使用對(duì)象-值元組數(shù)組:
const?foo?=?{?name:?'foo'?};const?bar?=?{?name:?'bar'?};
const?kindOfMap?=?[
??[foo,?'Foo?related?data'],
??[bar,?'Bar?related?data']
]
kindOfMap 是一個(gè)數(shù)組,包含對(duì)象和關(guān)聯(lián)值的對(duì)。
這種方法最大的問(wèn)題是按鍵訪問(wèn)值的復(fù)雜度O(n),咱們必須遍歷整個(gè)數(shù)組才能通過(guò)鍵獲得所需的值。
function?getByKey(kindOfMap,?key)?{??for?(const?[k,?v]?of?kindOfMap)?{
????if?(key?===?k)?{
??????return?v;
????}
??}
??return?undefined;
}
getByKey(kindOfMap,?foo);?//?=>?'Foo?related?data'
WeakMap (Map的一個(gè)專(zhuān)門(mén)版本)不需要這么麻煩就能做到上面的事情:它只接受對(duì)象作為鍵。
Map 和 Weakmap 之間的主要區(qū)別是,Weakmap 允許對(duì)鍵對(duì)象進(jìn)行垃圾收集,從而防止內(nèi)存泄漏。
好了,用 WeakMap 重構(gòu)上面的代碼就變得很簡(jiǎn)單了:
const?foo?=?{?name:?'foo'?};const?bar?=?{?name:?'bar'?};
const?mapOfObjects?=?new?WeakMap();
mapOfObjects.set(foo,?'Foo?related?data');
mapOfObjects.set(bar,?'Bar?related?data');
mapOfObjects.get(foo);?//?=>?'Foo?related?data'
與 Map 相反,WeakMap 只接受對(duì)象作為鍵,并少了一些方法。
2. map 對(duì)鍵名沒(méi)有限制
JS 中的任何對(duì)象都從原型對(duì)象繼承屬性,普通對(duì)象也是如此。
如果重寫(xiě)從原型繼承的屬性,則可能會(huì)破壞依賴這些原型屬性的代碼:
function?isPlainObject(value)?{??return?value.toString()?===?'[object?Object]';
}
const?actor?=?{
??name:?'Harrison?Ford',
??toString:?'Actor:?Harrison?Ford'
};
//?Does?not?work!
isPlainObject(actor);?//?TypeError:?value.toString?is?not?a?function
在對(duì)象參與者上定義的屬性 toString 覆蓋從原型繼承的 toString() 方法。這中斷了isObject(),因?yàn)樗蕾囉?toString() 方法。
檢查普通對(duì)象從原型繼承的屬性和方法的列表, 避免使用這些方法名定義自定義屬性。
例如,假設(shè)有一個(gè)管理某些自定義字段的用戶界面。用戶可以通過(guò)指定名稱(chēng)和值來(lái)添加自定義字段:
將定制字段的狀態(tài)存儲(chǔ)到普通對(duì)象中會(huì)很方便:
const?userCustomFields?=?{??'color':????'blue',
??'size':?????'medium',
??'toString':?'A?blue?box'
};
但是用戶可能會(huì)選擇一個(gè)自定義字段名稱(chēng),例如toString(如示例中所示),構(gòu)造函數(shù)等,這可能會(huì)破壞咱們的對(duì)象。
不要使用用戶輸入的值作為普通對(duì)象上鍵。
map 沒(méi)有這個(gè)問(wèn)題,鍵值名稱(chēng)不受限制:
function?isMap(value)?{??return?value.toString()?===?'[object?Map]';
}
const?actorMap?=?new?Map();
actorMap.set('name',?'Harrison?Ford');
actorMap.set('toString',?'Actor:?Harrison?Ford');
//?Works!
isMap(actorMap);?//?=>?true
不管 actorMap 有一個(gè)名為toString的屬性,toString()方法都可以正常工作。
3. map 是可迭代
為了遍歷普通對(duì)象的屬性,必須使用其他的輔助靜態(tài)函數(shù),如 Object.keys()或 Object.entries():
const?colorsHex?=?{??'white':?'#FFFFFF',
??'black':?'#000000'
};
for?(const?[color,?hex]?of?Object.entries(colorsHex))?{
??console.log(color,?hex);
}
//?'white'?'#FFFFFF'
//?'black'?'#000000'
Object.entries(colorsHex) 返回從對(duì)象提取的鍵值對(duì)數(shù)組。
但是,map 本身是可迭代的:
const?colorsHexMap?=?new?Map();colorsHexMap.set('white',?'#FFFFFF');
colorsHexMap.set('black',?'#000000');
for?(const?[color,?hex]?of?colorsHexMap)?{
??console.log(color,?hex);
}
//?'white'?'#FFFFFF'
//?'black'?'#000000'
colorsHexMap是可迭代。可以在任何接受迭代的地方使用它:for()循環(huán),展開(kāi)運(yùn)算符[...map]。
map 提供了返回可迭代方法:map.keys() 遍歷鍵,map.values() 遍歷值
4. map 的大小
普通對(duì)象的另一個(gè)問(wèn)題是,您無(wú)法立馬知道它包含的屬性的數(shù)量。
const?exams?=?{??'John?Smith':?'10?points',
??'Jane?Doe':?'8?points',
};
Object.keys(exams).length;?//?=>?2
要確定 exams 的大小,必須通過(guò)所有鍵來(lái)確定它們的數(shù)量。
map 提供了 size 屬性,表示屬性的數(shù)量。
const?examsMap?=?new?Map([??['John?Smith',?'10?points'],
??['Jane?Doe',?'8?points'],
]);
examsMap.size;?//?=>?2
確定 map 的屬性的數(shù)量更加簡(jiǎn)單:examsMap.size。
總結(jié)
普通 JS 對(duì)象通常可以很好地保存結(jié)構(gòu)化數(shù)據(jù),但它們也有一些局限性:
只能用字符串或 sybmol 作為鍵
自己的對(duì)象屬性可能會(huì)與從原型繼承的屬性鍵沖突(例如 toString,constructor等)。
對(duì)象不能用作鍵
所有這些問(wèn)題都可以通過(guò) map 輕松解決。而且,它們提供了諸如迭代器和易于進(jìn)行大小查找之類(lèi)的好處。
不要將 map 當(dāng)作普通對(duì)象的替代品,而應(yīng)視為是普通對(duì)象補(bǔ)充。
你還知道 map 比普通物體的其他好處嗎?請(qǐng)?jiān)谙路搅粞浴?/p>
原文:https://dmitripavlutin.com/maps-vs-plain-objects-javascript/
作者:Dmitri Pavlutin ?譯者:前端小智 ?來(lái)源:dmitripavlutin
交流
Vue 中如何讓 input 聚焦?
高級(jí) Vue 技巧:控制父類(lèi)的 slot
如何構(gòu)建運(yùn)行良好的Vue組件
如何在 Vue 中對(duì)事件進(jìn)行防抖和節(jié)流?(小智的第三個(gè)視頻)
總結(jié)
以上是生活随笔為你收集整理的js map对象遍历_何时使用 Map 来代替变通的 JS 对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: micopython 18b20_Mic
- 下一篇: ioc spring 上机案例_Spri