详解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实现网页自动刷新可制作节日倒计时效果
May 27 Javascript
JavaScript中的索引数组、关联数组和静态数组、动态数组讲解
Nov 08 Javascript
jQuery中position()方法用法实例
Jan 16 Javascript
js实现touch移动触屏滑动事件
Apr 17 Javascript
JS+CSS实现简易实用的滑动门菜单效果
Sep 18 Javascript
分享JavaScript与Java中MD5使用两个例子
Dec 23 Javascript
Vue.js每天必学之方法与事件处理器
Sep 06 Javascript
JS三目运算(三元运算)方法详解
Mar 01 Javascript
vue插件vue-resource的使用笔记(小结)
Aug 04 Javascript
Vue编写多地区选择组件
Aug 21 Javascript
vue-router的两种模式的区别
May 30 Javascript
JavaScript 函数用法详解【函数定义、参数、绑定、作用域、闭包等】
May 12 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
收音机怀古---春雷3P7图片欣赏
2021/03/02 无线电
php更新修改excel中的内容实例代码
2014/02/26 PHP
php编写简单的文章发布程序
2015/06/18 PHP
phpstudy的php版本自由修改的方法
2017/10/18 PHP
PHP封装的分页类与简单用法示例
2019/02/25 PHP
javascript中创建对象的三种常用方法
2010/12/30 Javascript
js的写法基础分析
2011/01/17 Javascript
如何检测JavaScript的各种类型
2016/07/30 Javascript
jQuery插件zTree实现更新根节点中第i个节点名称的方法示例
2017/03/08 Javascript
Bootstrap如何激活导航状态
2017/03/22 Javascript
67 个节约开发时间的前端开发者的工具、库和资源
2017/09/12 Javascript
详解layui弹窗父子窗口之间传参数的方法
2018/01/16 Javascript
原生js实现省市区三级联动代码分享
2018/02/12 Javascript
vue实现鼠标经过动画
2019/10/16 Javascript
使用JS location实现搜索框历史记录功能
2019/12/23 Javascript
javascript中的offsetWidth、clientWidth、innerWidth及相关属性方法
2020/05/14 Javascript
如何区分vue中的v-show 与 v-if
2020/09/08 Javascript
[00:32]10月24、25日 辉夜杯外卡赛附加赛开赛!
2015/10/23 DOTA
[51:26]VP vs VG 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
python递归查询菜单并转换成json实例
2017/03/27 Python
pycharm下打开、执行并调试scrapy爬虫程序的方法
2017/11/29 Python
Numpy 将二维图像矩阵转换为一维向量的方法
2018/06/05 Python
Python3使用SMTP发送带附件邮件
2020/06/16 Python
Python自定义一个类实现字典dict功能的方法
2019/01/19 Python
Python高级编程之继承问题详解(super与mro)
2019/11/19 Python
windows环境中利用celery实现简单任务队列过程解析
2019/11/29 Python
Python tensorflow实现mnist手写数字识别示例【非卷积与卷积实现】
2019/12/19 Python
CSS3 透明色 RGBA使用介绍
2013/08/06 HTML / CSS
俄罗斯汽车零件和配件在线商店:CarvilleShop
2019/11/29 全球购物
实习生自荐信范文
2013/11/13 职场文书
歌唱比赛获奖感言
2014/01/21 职场文书
总经理岗位职责描述
2014/02/08 职场文书
网络优化专员求职信
2014/05/04 职场文书
乡镇党的群众路线对照检查材料
2014/09/24 职场文书
如何做好员工培训计划?
2019/07/09 职场文书
2019年市场部个人述职报告(三篇)
2019/10/23 职场文书