详解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 相关文章推荐
Javascript 面向对象 继承
May 13 Javascript
JavaScript高级程序设计 客户端存储学习笔记
Sep 10 Javascript
JS实现漂亮的淡蓝色滑动门效果代码
Sep 23 Javascript
jquery ztree异步搜索(搜叶子)实践
Feb 25 Javascript
微信小程序 条件渲染详解
Oct 09 Javascript
最常见的左侧分类菜单栏jQuery实现代码
Nov 28 Javascript
BootStrap学习系列之布局组件(下拉,按钮组[toolbar],上拉)
Jan 03 Javascript
Vue.js 2.0和Cordova开发webApp环境搭建方法
Feb 26 Javascript
vue组件实践之可搜索下拉框功能
Nov 25 Javascript
js设计模式之单例模式原理与用法详解
Aug 15 Javascript
js 对象使用的小技巧实例分析
Nov 08 Javascript
JS前端使用canvas实现扩展物体类和事件派发
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
PHPlet在Windows下的安装
2006/10/09 PHP
PHP制作万年历
2015/01/07 PHP
tp5框架前台无限极导航菜单类实现方法分析
2020/03/29 PHP
AJAX架构之Dojo篇
2007/04/10 Javascript
jQuery动画特效实例教程
2014/08/29 Javascript
javascript实现滑动解锁功能
2014/12/31 Javascript
javascript判断移动端访问设备并解析对应CSS的方法
2015/02/05 Javascript
IE下使用jQuery重置iframe地址时内存泄露问题解决办法
2015/02/05 Javascript
js操作css属性实现div层展开关闭效果的方法
2015/05/11 Javascript
jquery中添加属性和删除属性
2015/06/03 Javascript
用jQuery.ajaxSetup实现对请求和响应数据的过滤
2016/12/20 Javascript
正则验证小数点后面只能有两位数的方法
2017/02/28 Javascript
利用imgareaselect辅助后台实现图片上传裁剪
2017/03/02 Javascript
js实现股票实时刷新数据案例
2017/05/14 Javascript
node.js express中app.param的用法详解
2017/07/16 Javascript
利用ES6实现单例模式及其应用详解
2017/12/09 Javascript
vue 标签属性数据绑定和拼接的实现方法
2018/05/17 Javascript
微信小程序公用参数与公用方法用法示例
2019/01/09 Javascript
如何使用proxy实现一个简单完整的MVVM库的示例代码
2019/09/17 Javascript
[01:29:46]DOTA2上海特级锦标赛C组资格赛#1 OG VS LGD第二局
2016/02/27 DOTA
python中实现将多个print输出合成一个数组
2018/04/19 Python
Python3多进程 multiprocessing 模块实例详解
2018/06/11 Python
Python 加密与解密小结
2018/12/06 Python
Python实现CNN的多通道输入实例
2020/01/17 Python
罗德与泰勒百货官网:Lord & Taylor
2016/08/12 全球购物
加拿大领先的牛仔零售商:Bluenotes
2018/01/22 全球购物
英国游戏机和游戏购物网站:365games.co.uk
2018/06/18 全球购物
美国林业供应商:Forestry Suppliers
2019/05/01 全球购物
最新大学生自我评价
2013/09/24 职场文书
财务会计专业毕业生自荐信
2013/10/19 职场文书
财务经理的岗位职责
2013/12/17 职场文书
电厂厂长岗位职责
2014/01/02 职场文书
运动会跳远广播稿
2014/02/04 职场文书
如何写好建议书
2014/03/13 职场文书
就业协议书
2014/09/12 职场文书
销售简历自我评价怎么写
2014/09/26 职场文书