详解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跨Iframe选择实现代码
Aug 19 Javascript
父子窗体间传递JSON格式的数据的代码
Dec 25 Javascript
addEventListener 的用法示例介绍
May 07 Javascript
jQuery添加/改变/移除CSS类及判断是否已经存在CSS
Aug 20 Javascript
jQuery添加和删除输入文本框标签代码
May 20 Javascript
BootStrap轻松实现微信页面开发代码分享
Oct 21 Javascript
Bootstrap免费字体和图标网站(值得收藏)
Mar 16 Javascript
详解angular部署到iis出现404解决方案
Aug 14 Javascript
Angular6项目打包优化的实现方法
Dec 15 Javascript
微信小程序纯文本实现@功能
Apr 08 Javascript
Vue3为什么这么快
Sep 23 Javascript
vue的webcamjs集成方式
Nov 16 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
利用laravel+ajax实现文件上传功能方法示例
2017/08/13 PHP
php实现 master-worker 守护多进程模式的实例代码
2019/07/20 PHP
layui数据表格自定义每页条数limit设置
2019/10/26 PHP
Thinkphp5框架中引入Markdown编辑器操作示例
2020/06/03 PHP
编写兼容IE和FireFox的脚本
2009/05/18 Javascript
JQuery操作表格(隔行着色,高亮显示,筛选数据)
2012/02/23 Javascript
javascript 获取模态窗口的滚动位置代码
2013/08/06 Javascript
利用javascript打开模态对话框(示例代码)
2014/01/11 Javascript
js实现三张图(文)片一起切换的banner焦点图
2015/08/25 Javascript
JavaScript学习笔记整理之引用类型
2016/01/22 Javascript
vue-router单页面路由
2017/06/17 Javascript
vue项目打包部署到服务器的方法示例
2018/08/27 Javascript
关于js陀螺仪的理解分析
2019/04/11 Javascript
微信小程序自定义弹窗滚动与页面滚动冲突的解决方法
2019/07/16 Javascript
vue实现将数据存入vuex中以及从vuex中取出数据
2019/11/08 Javascript
vue学习笔记之作用域插槽实例分析
2020/02/01 Javascript
jquery+ajax实现异步上传文件显示进度条
2020/08/17 jQuery
django 解决manage.py migrate无效的问题
2018/05/27 Python
详解Python3中ceil()函数用法
2019/02/19 Python
树莓派与PC端在局域网内运用python实现即时通讯
2019/06/22 Python
在OpenCV里实现条码区域识别的方法示例
2019/12/04 Python
python代码如何注释
2020/06/01 Python
Python pytesseract验证码识别库用法解析
2020/06/29 Python
Python爬虫小例子——爬取51job发布的工作职位
2020/07/10 Python
自定义html标记替换html5新增元素
2008/10/17 HTML / CSS
Otticanet意大利:最顶尖的世界名牌眼镜, 能得到打折季的价格
2019/03/10 全球购物
Whistles官网:英国女装品牌
2020/08/14 全球购物
解释一下Windows的消息机制
2014/01/30 面试题
公务员诚信承诺书
2014/05/26 职场文书
2014年妇幼卫生工作总结
2014/12/09 职场文书
小升初自荐信怎么写
2015/03/26 职场文书
python pyhs2 的安装操作
2021/04/07 Python
javascript遍历对象的五种方式实例代码
2021/10/24 Javascript
Javascript使用integrity属性进行安全验证
2021/11/07 Javascript
python人工智能human learn绘图可创建机器学习模型
2021/11/23 Python
MySQL优化及索引解析
2022/03/17 MySQL