详解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+ajax请求data显示在GridView上(asp.net)
Aug 27 Javascript
一些常用弹出窗口/拖放/异步文件上传等实用代码
Jan 06 Javascript
js绑定事件this指向发生改变的问题解决方法
Apr 23 Javascript
深入Javascript函数、递归与闭包(执行环境、变量对象与作用域链)使用详解
May 08 Javascript
javascript中数组的冒泡排序使用示例
Dec 18 Javascript
vue省市区三联动下拉选择组件的实现
Apr 28 Javascript
Node.js中多进程模块Cluster的介绍与使用
May 27 Javascript
微信小程序排坑指南详解
May 23 Javascript
js获取 gif 的帧数的代码实例
Sep 10 Javascript
微信小程序点击按钮动态切换input的disabled禁用/启用状态功能
Mar 07 Javascript
微信小程序之滑动页面隐藏和显示组件功能的实现代码
Jun 19 Javascript
JS事件循环机制event loop宏任务微任务原理解析
Aug 04 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
用Json实现PHP与JavaScript间数据交换的方法详解
2013/06/20 PHP
神盾加密解密教程(二)PHP 神盾解密
2014/06/08 PHP
CI框架出现mysql数据库连接资源无法释放的解决方法
2016/05/17 PHP
php使用escapeshellarg时中文被过滤的解决方法
2016/07/10 PHP
使用tp框架和SQL语句查询数据表中的某字段包含某值
2019/10/18 PHP
javaScript - 如何引入js代码
2021/03/09 Javascript
JavaScript函数、方法、对象代码
2008/10/29 Javascript
用Javascript数组处理多个字符串的连接问题
2009/08/20 Javascript
javascript alert乱码的解决方法
2013/11/05 Javascript
JavaScript 32位整型无符号操作示例
2013/12/08 Javascript
js实现刷新iframe的方法汇总
2015/04/27 Javascript
详谈LABJS按需动态加载js文件
2015/05/07 Javascript
ES6下子组件调用父组件的方法(推荐)
2018/02/23 Javascript
Vue js 的生命周期(看了就懂)(推荐)
2019/03/29 Javascript
AngularJS动态生成select下拉框的方法实例
2019/11/17 Javascript
JS实现图片切换特效
2019/12/23 Javascript
通过js随机函数Math.random实现乱序
2020/05/19 Javascript
微信小程序实现自定义底部导航
2020/11/18 Javascript
[03:24]CDEC.Y赛前采访 努力备战2016国际邀请赛中国区预选赛
2016/06/25 DOTA
通过mod_python配置运行在Apache上的Django框架
2015/07/22 Python
python实现搜索本地文件信息写入文件的方法
2016/02/22 Python
python利用MethodType绑定方法到类示例代码
2017/08/27 Python
python数据结构之列表和元组的详解
2017/09/23 Python
Python基于分水岭算法解决走迷宫游戏示例
2017/09/26 Python
Python+selenium实现自动循环扔QQ邮箱漂流瓶
2018/05/29 Python
BP神经网络原理及Python实现代码
2018/12/18 Python
python使用正则表达式(Regular Expression)方法超详细
2019/12/30 Python
什么是servlet
2012/05/08 面试题
中国文明网签名寄语
2014/01/18 职场文书
安全生产检讨书
2014/01/21 职场文书
前台接待员岗位职责
2015/04/15 职场文书
2015年学校安全工作总结
2015/04/22 职场文书
2015年迎新晚会策划书
2015/07/16 职场文书
简历自我评价范文
2019/04/24 职场文书
图解上海144收音机
2021/04/22 无线电
嵌入式Redis服务器在Spring Boot测试中的使用教程
2021/07/21 Redis