详解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的Tab选项框效果代码(插件)
Mar 01 Javascript
利用jQuery接受和处理xml数据的代码(.net)
Mar 28 Javascript
smartcrop.js智能图片裁剪库
Oct 14 Javascript
jQuery EasyUI Pagination实现分页的常用方法
May 21 Javascript
bootstrap table动态加载数据示例代码
Mar 25 Javascript
JS实现微信里判断页面是否被分享成功的方法
Jun 06 Javascript
用Vue写一个分页器的示例代码
Apr 22 Javascript
利用Angular7开发一个Radio组件的全过程
Jul 11 Javascript
如何利用Node.js与JSON搭建简单的动态服务器
Jun 16 Javascript
Nuxt.js 静态资源和打包的操作
Nov 06 Javascript
Vue实现摇一摇功能(兼容ios13.3以上)
Jan 26 Vue.js
JavaScript执行机制详细介绍
Dec 06 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入门学习知识点八 PHP中for循环基本应用之九九乘法口绝表
2011/07/14 PHP
PHP获取服务器端信息的方法
2014/11/28 PHP
php设计模式之策略模式应用案例详解
2019/06/17 PHP
Extjs 几个方法的讨论
2010/01/28 Javascript
如何用js控制frame的隐藏或显示的解决办法
2013/03/20 Javascript
原生javascript实现图片滚动、延时加载功能
2015/01/12 Javascript
jQuery实现带有动画效果的回到顶部和底部代码
2015/11/04 Javascript
JavaScript学习小结之使用canvas画“哆啦A梦”时钟
2016/07/24 Javascript
JS获取鼠标选中的文字
2016/08/10 Javascript
JavaScript函数参数的传递方式详解
2017/03/06 Javascript
微信小程序 判断手机号的实现代码
2017/04/19 Javascript
Angular.js中定时器循环的3种方法总结
2017/04/27 Javascript
JavaScript在控件上添加倒计时功能的实现代码
2017/07/04 Javascript
jquery手机触屏滑动拼音字母城市选择器的实例代码
2017/12/11 jQuery
微信小程序实现页面跳转传值以及获取值的方法分析
2017/12/18 Javascript
JS实现二维数组横纵列转置的方法
2018/04/17 Javascript
基于vue.js实现分页查询功能
2018/12/29 Javascript
JS实现根据数组对象的某一属性排序操作示例
2019/01/14 Javascript
详解mpvue中使用vant时需要注意的onChange事件的坑
2019/05/16 Javascript
python 中文字符串的处理实现代码
2009/10/25 Python
python自动化工具日志查询分析脚本代码实现
2013/11/26 Python
pandas 数据索引与选取的实现方法
2019/06/21 Python
python实现几种归一化方法(Normalization Method)
2019/07/31 Python
Python接口自动化测试框架运行原理及流程
2020/11/30 Python
html+css3实现的登录界面
2020/12/09 HTML / CSS
static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
2015/02/22 面试题
生日寿宴答谢词
2014/01/19 职场文书
应届生找工作求职信
2014/06/24 职场文书
2014办公室副主任四风对照检查材料思想汇报
2014/09/20 职场文书
大学生见习报告范文
2014/11/03 职场文书
2014年统计工作总结
2014/11/21 职场文书
婚庆答谢词
2015/01/04 职场文书
培根随笔读书笔记
2015/07/01 职场文书
《珍珠鸟》教学反思
2016/02/16 职场文书
2016年学校党支部创先争优活动总结
2016/04/05 职场文书
祝福语集锦:送给闺蜜的生日祝福语
2019/10/08 职场文书