詳解JavaScript中Hash Map映射結(jié)構(gòu)的實(shí)現(xiàn)
Hash Map通常在JavaScript中作為一個(gè)簡(jiǎn)單的來(lái)存儲(chǔ)鍵值對(duì)的地方。然而,Object并不是一個(gè)真正的哈希映射,如果使用不當(dāng)可能會(huì)帶來(lái)潛在的問(wèn)題。而且JavaScript可能不提供本地哈希映射(至少不是跨瀏覽器兼容的),有一個(gè)更好的聲明對(duì)象屬性的方法。
Hash Map的簡(jiǎn)單實(shí)現(xiàn):
var hashMap = { Set : function(key,value){this[key] = value}, Get : function(key){return this[key]}, Contains : function(key){return this.Get(key) == null?false:true}, Remove : function(key){delete this[key]} }
使用方法示例:
hashMap.Set("name","John Smith"); hashMap.Set("age",24); hashMap.Get("name");//John Smith hashMap.Contains("title");//false hashMap.Contains("name");//true hashMap.Remove("age");
在Object聲明成員的問(wèn)題
該問(wèn)題可能緣于對(duì)象原型鏈的繼承機(jī)制。就拿toString方法來(lái)說(shuō),如果使用in操作符來(lái)判斷對(duì)象是否存在的話:
var map = {}; 'toString' in map; // true
因?yàn)閕n操作符會(huì)從所有原型繼續(xù)對(duì)象查找該對(duì)象是否存在。要解決這個(gè)問(wèn)題,可使用hasOwnProperty方法檢測(cè)該對(duì)象是否存在:
var map = {}; map.hasOwnProperty('toString'); // false
這個(gè)方法可以工作地很正常,不過(guò)如果你定義了一個(gè)hasOwnProperty屬性那可能就麻煩了:
var map = {}; map.hasOwnProperty = 'foo'; map.hasOwnProperty('hasOwnproperty'); // TypeError
快速修復(fù)這個(gè)的方法是使用原生對(duì)象的方法。
var map = {}; map.hasOwnProperty = 'foo'; {}.hasOwnProperty.call(map, 'hasOwnproperty'); // true
這種方法不會(huì)引起任何問(wèn)題,每次你判斷對(duì)象中的屬性是否存在時(shí)都要過(guò)濾掉原型鏈中的方法:
var map = {}; var has = {}.hasOwnProperty; for(var key in map){ if(has.call(map, key)){ // do something } }
裸對(duì)象
創(chuàng)建一個(gè)真正的Hash Map的訣竅是解藕所有的原型對(duì)象。我們可以通過(guò) Object.create 來(lái)實(shí)現(xiàn)這個(gè)效果
var obj = {}; // is equivalent to: var obj = Object.create(Object.prototype);
另外,這種方法可以讓你完全放棄原型,直接使用 null 來(lái)繼承。
var map = Object.create(null); map instanceof Object; // false Object.prototype.isPrototypeOf(map); // false Object.getPrototypeOf(map); // null
這些裸對(duì)象(或字典)是作為Hasp Map的理想選擇。因?yàn)椴粫?huì)有任何沖突,它會(huì)抵制任何類型轉(zhuǎn)換,比如這樣就會(huì)產(chǎn)生錯(cuò)誤。
var map = Object.create(null); map + ""; // TypeError: Cannot convert object to primitive value
這里沒(méi)有任何保留字,它就是為Hash Map設(shè)計(jì)的,比如。
var map = Object.create(null); 'toString' in map; // false更進(jìn)一步,for ... in 循環(huán)變得更加簡(jiǎn)單了,我們只需要把循環(huán)寫成這樣。
var map = Object.create(null); for(var key in map){ // do something }
除了這些區(qū)別,它使用起來(lái)跟一般的Object鍵值存儲(chǔ)沒(méi)有任何區(qū)別。該對(duì)象可以被序列化,可以聲明原型和被繼承,上下文變量的使用也是一樣的。
var map = Object.create(null); Object.defineProperties(map, { 'foo': { value: 1, enumerable: true }, 'bar': { value: 2, enumerable: false } }); map.foo; // 1 map['bar']; // 2 JSON.stringify(map); // {"foo":1} {}.hasOwnProperty.call(map, 'foo'); // true {}.propertyIsEnumerable.call(map, 'bar'); // false
甚至上面提到的那些變量檢測(cè)方法同樣適用。
var map = Object.create(null); typeof map; // object {}.toString.call(map); // [object Object] {}.valueOf.call(map); // Object {}
相關(guān)文章
JS實(shí)現(xiàn)圖片預(yù)加載之無(wú)序預(yù)加載功能代碼
這篇文章主要介紹了JS實(shí)現(xiàn)圖片預(yù)加載之無(wú)序預(yù)加載功能代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-05-05JavaScript中Promise的簡(jiǎn)單使用及其原理詳解
Promise是ES6最重要的特性之一,今天小編就來(lái)帶大家一起系統(tǒng)且細(xì)致的研究一下Promise的用法以及原理,感興趣的小伙伴可以學(xué)習(xí)一下哦2023-03-03JavaScript實(shí)現(xiàn)單擊下拉框選擇直接跳轉(zhuǎn)頁(yè)面的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)單擊下拉框選擇直接跳轉(zhuǎn)頁(yè)面的方法,涉及javascript控制頁(yè)面跳轉(zhuǎn)的相關(guān)技巧,需要的朋友可以參考下2015-07-07如何判斷鼠標(biāo)是否在DIV的區(qū)域內(nèi)
通過(guò)mouseover,mouseout來(lái)觸發(fā)事件,才判斷鼠標(biāo)是否在該區(qū)域。 但是這種方法的局限性就是,必須要觸發(fā)mouseover,或mouseout,mouseleave事件才能知道2013-11-11微信小程序用戶授權(quán),以及判斷登錄是否過(guò)期的方法
這篇文章主要介紹了微信小程序用戶授權(quán)及判斷登錄是否過(guò)期,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05基于JavaScript實(shí)現(xiàn)簡(jiǎn)單的音樂(lè)音譜圖效果
我們經(jīng)??吹皆诼?tīng)樂(lè)音的時(shí)候,會(huì)有音譜圖隨著音樂(lè)的節(jié)奏不斷變化給人視覺(jué)上的享受,那么本文我們就來(lái)通過(guò)JavaScript來(lái)實(shí)現(xiàn)這一效果,感興趣的可以了解下2023-11-11JavaScript File API實(shí)現(xiàn)文件上傳預(yù)覽
這篇文章主要為大家介紹了JavaScript File API實(shí)現(xiàn)文件上傳預(yù)覽,F(xiàn)ile API將極大地方便 Web 端的文件上傳等操作,本文將介紹 File API的概況,并用兩個(gè)實(shí)例展示File API的應(yīng)用,感興趣的小伙伴們可以參考一下2016-02-02