详解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中的数学函数
Apr 04 Javascript
JSON 学习之完全手册 图文
May 29 Javascript
javascript强制点击广告的方法
Feb 06 Javascript
JavaScript中的闭包介绍
Mar 15 Javascript
avalon js实现仿google plus图片多张拖动排序附源码下载
Sep 24 Javascript
javascript中select下拉框的用法总结
Jan 07 Javascript
jQuery判断浏览器并动态调整select宽度的方法
Mar 02 Javascript
基于vue2.0实现简单轮播图
Nov 27 Javascript
使用vue-cli创建项目的图文教程(新手入门篇)
May 02 Javascript
详解element-ui中form验证杂记
Mar 04 Javascript
JS字符串与二进制的相互转化实例代码详解
Jun 28 Javascript
js前端对于大量数据的展示方式及处理方法
Dec 02 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
长波有什么东西
2021/03/01 无线电
Yii实现MySQL多数据库和读写分离实例分析
2014/12/03 PHP
PHP采用超长(超大)数字运算防止数字以科学计数法显示的方法
2016/04/01 PHP
PHP将字符串首字母大小写转换的实例
2017/01/21 PHP
PHP高精确度运算BC函数库实例详解
2017/08/15 PHP
javascript预览上传图片发现的问题的解决方法
2010/11/25 Javascript
同域jQuery(跨)iframe操作DOM(实例讲解)
2013/12/19 Javascript
js数组去重的常用方法总结
2014/01/24 Javascript
jquery中get和post的简单实例
2014/02/04 Javascript
鼠标悬浮停留三秒后自动显示大图js代码
2014/09/09 Javascript
innerHTML属性,outerHTML属性,textContent属性,innerText属性区别详解
2015/03/13 Javascript
JQuery CheckBox(复选框)操作方法汇总
2015/04/15 Javascript
JS获取当前使用的浏览器名字以及版本号实现方法
2016/08/19 Javascript
AJAX和jQuery动态加载数据的实现方法
2016/12/05 Javascript
jQuery为DOM动态追加事件的方法
2017/02/16 Javascript
JS自动生成动态HTML验证码页面
2017/06/14 Javascript
Angular4 组件通讯方法大全(推荐)
2018/07/12 Javascript
element-ui 中的table的列隐藏问题解决
2018/08/24 Javascript
Nuxt.js SSR与权限验证的实现
2018/11/21 Javascript
webpack4从0搭建组件库的实现
2020/11/29 Javascript
[52:20]DOTA2-DPC中国联赛正赛 SAG vs XGBO3 第一场 3月5日
2021/03/11 DOTA
Python爬取Coursera课程资源的详细过程
2014/11/04 Python
python中的闭包用法实例详解
2015/05/05 Python
详解python使用turtle库来画一朵花
2019/03/21 Python
PyQt5连接MySQL及QMYSQL driver not loaded错误解决
2020/04/29 Python
Django中如何用xlwt生成表格的方法步骤
2021/01/31 Python
如何在Cookie里面保存Unicode和国际化字符
2013/05/25 面试题
大学生护理专业自荐信
2013/10/03 职场文书
中专药剂专业应届毕的自我评价
2013/12/27 职场文书
大学生职业生涯规划范文——找准自我,定位人生
2014/01/23 职场文书
秸秆管理实施方案
2014/03/15 职场文书
八年级上册语文教学计划
2015/01/22 职场文书
财务部会计岗位职责
2015/02/03 职场文书
Nginx URL重写rewrite机制原理及使用实例
2021/04/01 Servers
基于Pygame实现简单的贪吃蛇游戏
2021/12/06 Python
Java存储没有重复元素的数组
2022/04/29 Java/Android