详解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脚本
Dec 03 Javascript
firefox下input type="file"的size是多大
Oct 24 Javascript
仅IE支持clearAttributes/mergeAttributes方法使用介绍
May 04 Javascript
判断JS对象是否拥有某属性的方法推荐
May 12 Javascript
knockoutjs动态加载外部的file作为component中的template数据源的实现方法
Sep 01 Javascript
微信小程序 devtool隐藏的秘密
Jan 21 Javascript
JS实现匀加速与匀减速运动的方法示例
Sep 04 Javascript
jQuery模拟12306城市选择框功能简单实现方法示例
Aug 13 jQuery
vue组件中iview的modal组件爬坑问题之modal的显示与否应该是使用v-show
Apr 12 Javascript
关于vue利用postcss-pxtorem进行移动端适配的问题
Nov 20 Javascript
jQuery实现弹幕特效
Nov 29 jQuery
Vue组件通信入门之Provide和Inject机制
Dec 29 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中使用Oracle数据库(6)
2006/10/09 PHP
第九节--绑定
2006/11/16 PHP
通俗易懂的php防注入代码
2010/04/07 PHP
PHP数组的交集array_intersect(),array_intersect_assoc(),array_inter_key()函数的小问题
2011/05/29 PHP
php面象对象数据库操作类实例
2014/12/02 PHP
PHP+mysql实现从数据库获取下拉树功能示例
2017/01/06 PHP
PHP里面把16进制的图片数据显示在html的img标签上(实现方法)
2017/05/02 PHP
google地图的路线实现代码
2009/08/20 Javascript
禁止选中文字兼容IE、Chrome、FF等
2013/09/04 Javascript
jquery动画效果学习笔记(8种效果)
2015/11/13 Javascript
javascript中的作用域和闭包详解
2016/01/13 Javascript
javascript+HTML5自定义元素播放焦点图动画
2016/02/21 Javascript
第一次接触神奇的Bootstrap网格系统
2016/07/27 Javascript
JS获取浮动(float)元素的style.left值为空的快速解决办法
2017/02/19 Javascript
Bootstrap Table使用整理(五)之分页组合查询
2017/06/09 Javascript
使用jQuery实现简单的tab框实例
2017/08/22 jQuery
vue.js仿hover效果的实现方法示例
2019/01/28 Javascript
vue基础之事件v-onclick="函数"用法示例
2019/03/11 Javascript
微信小程序城市选择及搜索功能的方法
2019/03/22 Javascript
JS内置对象和Math对象知识点详解
2020/04/03 Javascript
[01:12](回顾)DOTA2国际邀请赛,全世界DOTAer的盛宴
2014/07/01 DOTA
[36:29]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 LGD vs TNC
2018/04/02 DOTA
Python随手笔记第一篇(2)之初识列表和元组
2016/01/23 Python
Python中struct模块对字节流/二进制流的操作教程
2017/01/21 Python
python 删除大文件中的某一行(最有效率的方法)
2017/08/19 Python
python如何定义带参数的装饰器
2018/03/20 Python
Python查找第n个子串的技巧分享
2018/06/27 Python
手把手教你如何用Pycharm2020.1.1配置远程连接的详细步骤
2020/08/07 Python
python dict如何定义
2020/09/02 Python
世界上最大的字体市场:MyFonts
2020/01/10 全球购物
写一个函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度
2015/11/18 面试题
会计电算化专业毕业生推荐信
2013/12/24 职场文书
公司道歉信范文
2014/01/09 职场文书
决定成败的关键——创业计划书
2014/01/24 职场文书
校长四风对照检查材料
2014/09/27 职场文书
贪污检举信范文
2015/03/02 职场文书