详解JavaScript中Hash Map映射结构的实现


Posted in Javascript onMay 21, 2016

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 {}
Javascript 相关文章推荐
用js实现的页面关键字密度查询代码
Dec 27 Javascript
javascript 多级checkbox选择效果
Aug 20 Javascript
判断用户的在线状态 onbeforeunload事件
Mar 05 Javascript
js调用后台servlet方法实例
Jun 09 Javascript
JQuery在页面中添加和除移DOM示例代码
Jun 24 Javascript
jQuery中trigger()方法用法实例
Jan 19 Javascript
js检测iframe是否加载完成的方法
Nov 26 Javascript
bootstrap模态框垂直居中效果
Dec 03 Javascript
JS实现点击表头表格自动排序(含数字、字符串、日期)
Jan 22 Javascript
ionic2屏幕适配实现适配手机、平板等设备的示例代码
Aug 11 Javascript
微信小程序bindinput与bindsubmit的区别实例分析
Apr 17 Javascript
Vue.js实现可编辑的表格
Dec 11 Javascript
简单掌握JavaScript中const声明常量与变量的用法
May 21 #Javascript
基于javascript实现表格的简单操作
May 21 #Javascript
javascript检测移动设备横竖屏
May 21 #Javascript
Ext JS框架中日期函数的用法及日期选择控件的实现
May 21 #Javascript
js+html5实现canvas绘制网页时钟的方法
May 21 #Javascript
JavaScript的Ext JS框架中的GridPanel组件使用指南
May 21 #Javascript
javascript RegExp 使用说明
May 21 #Javascript
You might like
php程序的国际化实现方法(利用gettext)
2011/08/14 PHP
PHP的Yii框架使用中的一些错误解决方法与建议
2015/08/21 PHP
php图像验证码生成代码
2017/06/08 PHP
番茄的表单验证类代码修改版
2008/07/18 Javascript
从零开始学习jQuery (十) jQueryUI常用功能实战
2011/02/23 Javascript
从jquery的过滤器.filter()方法想到的
2013/09/29 Javascript
js实现类似于add(1)(2)(3)调用方式的方法
2015/03/04 Javascript
原生js获取元素样式的简单方法
2016/08/06 Javascript
js实现的xml对象转json功能示例
2016/12/24 Javascript
微信小程序--onShareAppMessage分享参数用处(页面分享)
2017/04/18 Javascript
jQuery Autocomplete简介_动力节点Java学院整理
2017/07/17 jQuery
php main 与 iframe 相互通讯类(js+php同域/跨域)
2017/09/14 Javascript
ES6/JavaScript使用技巧分享
2017/12/14 Javascript
JavaScript模块管理的简单实现方式详解
2019/06/15 Javascript
微信小程序实现Swiper轮播图效果
2019/11/22 Javascript
微信小程序如何实现点击图片放大功能
2020/01/21 Javascript
python操作redis的方法
2015/07/07 Python
基于Python实现一个简单的银行转账操作
2016/03/06 Python
查找python项目依赖并生成requirements.txt的方法
2018/07/10 Python
Python模块的加载讲解
2019/01/15 Python
python程序变成软件的实操方法
2019/06/24 Python
python自动化实现登录获取图片验证码功能
2019/11/20 Python
仓库班组长岗位职责
2013/12/12 职场文书
寒假实习自荐信
2014/01/26 职场文书
有创意的广告词
2014/03/18 职场文书
中秋节主持词
2014/04/02 职场文书
《故乡》教学反思
2014/04/10 职场文书
卫生院健康教育实施方案
2014/06/07 职场文书
六一儿童节开幕词
2015/01/29 职场文书
2016自主招生教师推荐信范文
2015/03/23 职场文书
作弊检讨书范文
2015/05/06 职场文书
企业党建工作总结2015
2015/05/26 职场文书
2016年公务员六五普法心得体会
2016/01/21 职场文书
自考生自我评价
2019/06/21 职场文书
海贼王十大潜力果实,路飞仅排第十,第一可毁世界(震震果实)
2022/03/18 日漫
javascript进阶篇深拷贝实现的四种方式
2022/07/07 Javascript