详解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模块化是什么及其优缺点介绍
Sep 02 Javascript
基于jQuery的判断iPad、iPhone、Android是横屏还是竖屏的代码
May 11 Javascript
js实例属性和原型属性示例详解
Nov 23 Javascript
javascript面向对象之定义成员方法实例分析
Jan 13 Javascript
JavaScript常用基础知识强化学习
Dec 09 Javascript
IOS中safari下的select下拉菜单文字过长不换行的解决方法
Sep 26 Javascript
jquery移除了live()、die(),新版事件绑定on()、off()的方法
Oct 26 Javascript
JS绘制微信小程序画布时钟
Dec 24 Javascript
Vue表单验证插件Vue Validator使用方法详解
Apr 07 Javascript
vue2.0使用v-for循环制作多级嵌套菜单栏
Jun 25 Javascript
关于js陀螺仪的理解分析
Apr 11 Javascript
JavaScript中this的学习笔记及用法整理
Feb 17 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
Terran兵种对照表
2020/03/14 星际争霸
用PHP和ACCESS写聊天室(八)
2006/10/09 PHP
php 数组的一个悲剧?
2011/05/11 PHP
php二分查找二种实现示例
2014/03/12 PHP
3个PHP多维数组转为一维数组的方法实例
2014/03/13 PHP
php利用gd库为图片添加水印
2016/11/09 PHP
PHP未登录自动跳转到登录页面
2016/12/21 PHP
thinkPHP框架实现的无限回复评论功能示例
2018/06/09 PHP
多个$(document).ready()的执行顺序实例分析
2014/07/26 Javascript
简单的jquery左侧导航栏和页面选中效果
2014/08/21 Javascript
js中数组排序sort方法的原理分析
2014/11/20 Javascript
jQuery实现的淡入淡出二级菜单效果代码
2015/09/15 Javascript
js中利用tagname和id获取元素的方法
2016/01/03 Javascript
JS通过Cookie判断页面是否为首次打开
2016/02/05 Javascript
js仿淘宝和百度文库的评分功能
2016/05/15 Javascript
javascript学习之json入门
2016/12/22 Javascript
如何用js判断dom是否有存在某class的值
2017/02/13 Javascript
微信小程序多张图片上传功能
2017/06/07 Javascript
JSON在Javascript中的使用(eval和JSON.parse的区别)详细解析
2017/09/05 Javascript
jQuery UI实现动画效果代码分享
2018/08/19 jQuery
Python的面向对象思想分析
2015/01/14 Python
Python 爬虫模拟登陆知乎
2016/09/23 Python
关于python的list相关知识(推荐)
2017/08/30 Python
http请求 request失败自动重新尝试代码示例
2018/01/25 Python
利用pandas进行大文件计数处理的方法
2018/07/25 Python
使用TensorFlow实现SVM
2018/09/06 Python
python从PDF中提取数据的示例
2020/10/30 Python
如何利用input事件来监听移动端的输入
2016/04/15 HTML / CSS
Html5 webRTC简单实现视频调用的示例代码
2020/09/23 HTML / CSS
信访工作者先进事迹
2014/01/17 职场文书
微笑服务演讲稿
2014/05/13 职场文书
四风问题对照检查材料整改措施
2014/09/27 职场文书
学校党委副书记个人对照检查材料思想汇报
2014/09/28 职场文书
教师个人年度总结
2015/02/11 职场文书
基于Golang 高并发问题的解决方案
2021/05/08 Golang
CSS3 Tab动画实例之背景切换动态效果
2021/08/23 HTML / CSS