详解JavaScript中Hash Map映射结构的实现
来源: 阅读:955 次 日期:2016-06-25 13:43:54
温馨提示: 小编为您整理了“详解JavaScript中Hash Map映射结构的实现”,方便广大网友查阅!

Hash Map通常在JavaScript中作为一个简单的来存储键值对的地方。然而,Object并不是一个真正的哈希映射,如果使用不当可能会带来潜在的问题。而且JavaScript可能不提供本地哈希映射(至少不是跨浏览器兼容的),有一个更好的声明对象属性的方法。

Hash Map的简单实现:

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声明成员的问题

该问题可能缘于对象原型链的继承机制。就拿toString方法来说,如果使用in操作符来判断对象是否存在的话:

var map = {};

'toString' in map; // true

因为in操作符会从所有原型继续对象查找该对象是否存在。要解决这个问题,可使用hasOwnProperty方法检测该对象是否存在:

var map = {};

map.hasOwnProperty('toString'); // false

这个方法可以工作地很正常,不过如果你定义了一个hasOwnProperty属性那可能就麻烦了:

var map = {};

map.hasOwnProperty = 'foo';

map.hasOwnProperty('hasOwnproperty'); // TypeError

快速修复这个的方法是使用原生对象的方法。

var map = {};

map.hasOwnProperty = 'foo';

{}.hasOwnProperty.call(map, 'hasOwnproperty'); // true

这种方法不会引起任何问题,每次你判断对象中的属性是否存在时都要过滤掉原型链中的方法:

var map = {};

var has = {}.hasOwnProperty;

for(var key in map){

 if(has.call(map, key)){

  // do something

 }

}

裸对象

创建一个真正的Hash Map的诀窍是解藕所有的原型对象。我们可以通过 Object.create 来实现这个效果

var obj = {};

// is equivalent to:

var obj = Object.create(Object.prototype);

另外,这种方法可以让你完全放弃原型,直接使用 null 来继承。

var map = Object.create(null);

map instanceof Object; // false

Object.prototype.isPrototypeOf(map); // false

Object.getPrototypeOf(map); // null

这些裸对象(或字典)是作为Hasp Map的理想选择。因为不会有任何冲突,它会抵制任何类型转换,比如这样就会产生错误。

var map = Object.create(null);

map + ""; // TypeError: Cannot convert object to primitive value

这里没有任何保留字,它就是为Hash Map设计的,比如。

var map = Object.create(null);

'toString' in map; // false

更进一步,for ... in 循环变得更加简单了,我们只需要把循环写成这样。

var map = Object.create(null);

for(var key in map){

 // do something

}

除了这些区别,它使用起来跟一般的Object键值存储没有任何区别。该对象可以被序列化,可以声明原型和被继承,上下文变量的使用也是一样的。

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

甚至上面提到的那些变量检测方法同样适用。

var map = Object.create(null);

typeof map; // object

{}.toString.call(map); // [object Object]

{}.valueOf.call(map); // Object {}

更多信息请查看网络编程
由于各方面情况的不断调整与变化, 提供的所有考试信息和咨询回复仅供参考,敬请考生以权威部门公布的正式信息和咨询为准!
关于我们 | 联系我们 | 人才招聘 | 网站声明 | 网站帮助 | 非正式的简要咨询 | 简要咨询须知 | 加入群交流 | 手机站点 | 投诉建议
工业和信息化部备案号:滇ICP备2023014141号-1 云南省教育厅备案号:云教ICP备0901021 滇公网安备53010202001879号 人力资源服务许可证:(云)人服证字(2023)第0102001523号
云南网警备案专用图标
联系电话:0871-65317125(9:00—18:00) 获取招聘考试信息及咨询关注公众号:hfpxwx
咨询QQ:526150442(9:00—18:00)版权所有:
云南网警报警专用图标
Baidu
map