详解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 相关文章推荐
[HTML/CSS/Javascript]WWTJS
Sep 25 Javascript
jQuery EasyUI中对表格进行编辑的实现代码
Jun 10 Javascript
深入领悟JavaScript中的面向对象
Nov 18 Javascript
js写的方法实现上传图片之后查看大图
Mar 05 Javascript
jQuery异步验证用户名是否存在示例代码
May 21 Javascript
Javascript调用函数方法的几种方式介绍
Mar 20 Javascript
JS+CSS实现的经典tab选项卡效果代码
Sep 16 Javascript
jQuery的Ajax用户认证和注册技术实例教程(附demo源码)
Dec 08 Javascript
AngularJS实现使用路由切换视图的方法
Jan 24 Javascript
完美解决jQuery的hover事件在IE中不停闪动的问题
Feb 10 Javascript
AngularJs 最新验证手机号码的实例,成功测试通过
Nov 26 Javascript
浅谈Vue项目骨架屏注入实践
Aug 05 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
AJAX for PHP简单表数据查询实例
2007/01/02 PHP
php根据年月获取季度的方法
2014/03/31 PHP
JQuery FlexiGrid的asp.net完美解决方案 dotNetFlexGrid-.Net原生的异步表格控件
2010/09/12 Javascript
jquery 实现二级/三级/多级联动菜单的思路及代码
2013/04/08 Javascript
JQuery表格内容过滤的实现方法
2013/07/05 Javascript
JavaScript实现找出数组中最长的连续数字序列
2014/09/03 Javascript
javascript操作数组详解
2014/12/17 Javascript
JavaScript实现将UPC转换成ISBN的方法
2015/05/26 Javascript
javascript的正则匹配方法学习
2016/02/24 Javascript
jQuery Mobile框架中的表单组件基础使用教程
2016/05/17 Javascript
vue分类筛选filter方法简单实例
2017/03/30 Javascript
web.js.字符串与正则表达式操作
2017/05/13 Javascript
Angular.js中$resource高大上的数据交互详解
2017/07/30 Javascript
jQuery的时间datetime控件在AngularJs中的使用实例(分享)
2017/08/17 jQuery
AngularJS中下拉框的高级用法示例
2017/10/11 Javascript
vue中v-text / v-html使用实例代码详解
2019/04/02 Javascript
php结合js实现多条件组合查询
2019/05/28 Javascript
浅谈Vue中render中的h箭头函数
2019/11/07 Javascript
JavaScript定时器常见用法实例分析
2019/11/15 Javascript
vue实现导航标题栏随页面滚动渐隐渐显效果
2020/03/12 Javascript
JavaScript鼠标悬停事件用法解析
2020/05/15 Javascript
JS实现密码框效果
2020/09/10 Javascript
Numpy中对向量、矩阵的使用详解
2019/10/29 Python
用python拟合等角螺线的实现示例
2019/12/27 Python
pytorch实现用CNN和LSTM对文本进行分类方式
2020/01/08 Python
python中数字是否为可变类型
2020/07/08 Python
Python函数递归调用实现原理实例解析
2020/08/11 Python
详解python3 GUI刷屏器(附源码)
2021/02/18 Python
乐高奥地利官方商店:LEGO Shop AT
2019/07/16 全球购物
.NET程序员的几道面试题
2012/06/01 面试题
房屋转让协议书范本
2014/04/11 职场文书
2014年巴西世界杯口号
2014/06/05 职场文书
社区护士演讲稿
2014/08/27 职场文书
秋季运动会广播稿(30篇)
2014/09/13 职场文书
某集团股份有限公司委托书样本
2014/09/24 职场文书
2014年法院工作总结
2014/11/24 职场文书