詳解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ì)抵制任何類(lèi)型轉(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)寫(xiě)成這樣。
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)文章
JavaScript設(shè)計(jì)模式策略模式案例分享
這篇文章主要介紹了JavaScript設(shè)計(jì)模式策略模式案例分享,策略設(shè)計(jì)模式就是指一個(gè)問(wèn)題匹配多個(gè)解決方法,不一定要用到哪一個(gè),而且有可能隨時(shí)增加多個(gè)方案2022-06-06
js實(shí)現(xiàn)內(nèi)容顯示并使用json傳輸數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)內(nèi)容顯示并使用json傳輸數(shù)據(jù)的方法,感興趣的小伙伴們可以參考一下2016-03-03
探析瀏覽器執(zhí)行JavaScript腳本加載與代碼執(zhí)行順序
本文主要基于向HTML頁(yè)面引入JavaScript的幾種方式,分析HTML中JavaScript腳本的執(zhí)行順序問(wèn)題,通過(guò)本文給大家分享瀏覽器執(zhí)行JavaScript腳本加載與代碼執(zhí)行順序,對(duì)瀏覽器執(zhí)行javascript及執(zhí)行順序相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2016-01-01
JavaScript獲取function所有參數(shù)名的方法
本文使用javascript獲取function所有參數(shù)名的方法,對(duì)js獲取function所有參數(shù)名感興趣的朋友一起學(xué)習(xí)吧2015-10-10
JavaScript重定向URL參數(shù)的兩種方法小結(jié)
關(guān)于JavaScript重定向URL參數(shù)的實(shí)現(xiàn)方法網(wǎng)站有很多,這篇文章的主要內(nèi)容是從網(wǎng)上查找,并進(jìn)行了修改,簡(jiǎn)單粗暴的實(shí)現(xiàn)使用JavaScript重置url參數(shù),文中給出了詳細(xì)的示例代碼和調(diào)用代碼,對(duì)大家的理解和學(xué)習(xí)很有幫助,感興趣的朋友們下面來(lái)一起看看吧。2016-10-10
Javascript的表單與驗(yàn)證-非空驗(yàn)證
JavaScript 可用來(lái)在數(shù)據(jù)被送往服務(wù)器前對(duì) HTML 表單中的這些輸入數(shù)據(jù)進(jìn)行驗(yàn)證。本文給大家介紹javascript的表單與驗(yàn)證-非空驗(yàn)證,對(duì)javascript表單驗(yàn)證相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2016-03-03

