详解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 相关文章推荐
基于JQuery 的消息提示框效果代码
Jul 31 Javascript
jquery用offset()方法获得元素的xy坐标
Sep 06 Javascript
js变形金刚文字特效代码分享
Aug 20 Javascript
jquery中validate与form插件提交的方式小结
Mar 26 Javascript
12个非常实用的JavaScript小技巧【推荐】
May 18 Javascript
JS小数运算出现多为小数问题的解决方法
Jun 02 Javascript
ThinkJS中如何使用MongoDB的CURD操作
Dec 13 Javascript
vue项目中用cdn优化的方法
Jan 03 Javascript
vue地区选择组件教程详解
May 04 Javascript
从零撸一个pc端vue的ui组件库( 计数器组件 )
Aug 08 Javascript
vue 实现走马灯效果
Oct 28 Javascript
vue-socket.io接收不到数据问题的解决方法
May 13 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
全国FM电台频率大全 - 5 内蒙古自治区
2020/03/11 无线电
PHP $_FILES函数详解
2011/03/09 PHP
PHP中对于浮点型的数据需要用不同的方法解决
2014/03/11 PHP
phpmyadmin配置文件现在需要绝密的短密码(blowfish_secret)的2种解决方法
2014/05/07 PHP
PHP查找与搜索数组元素方法总结
2015/06/12 PHP
PHP Static延迟静态绑定用法分析
2016/03/16 PHP
JavaScript Event事件学习第一章 Event介绍
2010/02/07 Javascript
深入理解JavaScript系列(8) S.O.L.I.D五大原则之里氏替换原则LSP
2012/01/15 Javascript
jQuery动态显示和隐藏datagrid中的某一列的方法
2013/12/11 Javascript
javascript history对象(历史记录)使用方法(实现浏览器前进后退)
2014/01/07 Javascript
node.js中的fs.writeFile方法使用说明
2014/12/14 Javascript
JS获取及设置TextArea或input文本框选择文本位置的方法
2015/03/24 Javascript
初识Javascript小结
2015/07/16 Javascript
JavaScript基本数据类型及值类型和引用类型
2015/08/25 Javascript
JavaScript简单获取页面图片原始尺寸的方法
2016/06/21 Javascript
jQuery实现鼠标选中文字后弹出提示窗口效果【附demo源码】
2016/09/05 Javascript
javascript使用 concat 方法对数组进行合并的方法
2016/09/08 Javascript
KnockoutJS 3.X API 第四章之表单value绑定
2016/10/10 Javascript
javascript实现数据双向绑定的三种方式小结
2017/03/09 Javascript
Vue.js 2.0学习教程之从基础到组件详解
2017/04/24 Javascript
jQuery remove()过滤被删除的元素(推荐)
2017/07/18 jQuery
jQuery Position方法使用和兼容性
2017/08/23 jQuery
详解如何用VUE写一个多用模态框组件模版
2018/09/27 Javascript
ES6 let和const定义变量与常量的应用实例分析
2019/06/27 Javascript
微信小程序自定义单项选择器样式
2019/07/25 Javascript
vue中beforeRouteLeave实现页面回退不刷新的示例代码
2019/11/01 Javascript
python图像处理之镜像实现方法
2015/05/30 Python
Django页面数据的缓存与使用的具体方法
2019/04/23 Python
在Pytorch中计算卷积方法的区别详解(conv2d的区别)
2020/01/03 Python
Matplotlib.pyplot 三维绘图的实现示例
2020/07/28 Python
Python selenium实现断言3种方法解析
2020/09/08 Python
CSS3实现任意图片lowpoly动画效果实例
2017/05/11 HTML / CSS
女性时尚在线:IVRose
2019/02/23 全球购物
大学生护理专业自荐信
2013/10/03 职场文书
导游词之沈阳清昭陵
2019/12/28 职场文书
深入浅析python3 依赖倒置原则(示例代码)
2021/07/09 Python