详解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 相关文章推荐
js实现简单模态窗口,背景灰显
Nov 14 Javascript
一个简单的js渐显(fadeIn)渐隐(fadeOut)类
Jun 19 Javascript
写自已的js类库需要的核心代码
Jul 16 Javascript
jquery配合css简单实现返回顶部效果
Sep 30 Javascript
juery框架写的弹窗效果适合新手
Nov 27 Javascript
微信小程序 开发之滑块视图容器(swiper)详解及实例代码
Feb 22 Javascript
在vue项目中引用Iview的方法
Sep 14 Javascript
JavaScript栈和队列相关操作与实现方法详解
Dec 07 Javascript
Vue入门学习笔记【基本概念、对象、过滤器、指令等】
Apr 13 Javascript
解决vue 表格table列求和的问题
Nov 06 Javascript
jquery ajax 请求小技巧实例分析
Nov 11 jQuery
vue 路由懒加载中给 Webpack Chunks 命名的方法
Apr 24 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
php时间戳转换代码详解
2019/08/04 PHP
laravel 解决paginate查询多个字段报错的问题
2019/10/22 PHP
jquery HotKeys轻松搞定键盘事件代码
2008/08/30 Javascript
Prototype Class对象学习
2009/07/19 Javascript
一个可以兼容IE FF的加为首页与加入收藏实现代码
2009/11/02 Javascript
javascript 解决表单仍然提交即使监听处理函数返回false
2010/03/14 Javascript
调试Javascript代码(浏览器F12及VS中debugger关键字)
2013/01/25 Javascript
仿百度的关键词匹配搜索示例
2013/09/25 Javascript
jQuery 1.9.1源码分析系列(十)事件系统之主动触发事件和模拟冒泡处理
2015/11/24 Javascript
基于原生js淡入淡出函数封装(兼容IE)
2016/10/20 Javascript
基于javascript的Form表单验证
2016/12/29 Javascript
微信小程序 连续旋转动画(this.animation.rotate)详解
2017/04/07 Javascript
基于twbsPagination.js分页插件使用心得(分享)
2017/10/21 Javascript
Vue项目全局配置页面缓存之按需读取缓存的实现详解
2018/08/01 Javascript
layui点击导航栏刷新tab页的示例代码
2018/08/14 Javascript
[04:26]2014DOTA2西雅图国际邀请赛 总决赛TOPPLAY
2014/07/22 DOTA
python运行其他程序的实现方法
2017/07/14 Python
使用python实现简单五子棋游戏
2019/06/18 Python
Djang的model创建的字段和参数详解
2019/07/27 Python
python django 原生sql 获取数据的例子
2019/08/14 Python
Python调用Windows API函数编写录音机和音乐播放器功能
2020/01/05 Python
flask利用flask-wtf验证上传的文件的方法
2020/01/17 Python
Pycharm如何自动生成头文件注释
2020/11/14 Python
基于canvas的骨骼动画的示例代码
2018/06/12 HTML / CSS
美国领先的奢侈手表在线零售商:WatchMaxx
2017/12/17 全球购物
戴尔美国官方折扣店:Dell Outlet
2018/02/13 全球购物
MADE法国:提供原创设计师家具
2018/09/18 全球购物
上海奥佳笔试题面试题
2016/11/16 面试题
程序集与命名空间有什么不同
2014/07/25 面试题
购房意向书范本
2014/04/01 职场文书
2014年党员干部四风问题自我剖析材料
2014/09/29 职场文书
离婚财产处理协议书
2014/09/30 职场文书
教师群众路线心得体会
2014/11/04 职场文书
员工辞职信怎么写
2015/02/27 职场文书
Feign调用全局异常处理解决方案
2021/06/24 Java/Android
MySQL开启事务的方式
2021/06/26 MySQL