详解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阻止同类型事件小结
Apr 19 Javascript
javascript函数重载解决方案分享
Feb 19 Javascript
JS中操作JSON总结
Dec 06 Javascript
IE浏览器不支持getElementsByClassName的解决方法
Aug 27 Javascript
JavaScript调试工具汇总
Dec 23 Javascript
jquery实现无限分级横向导航菜单的方法
Mar 12 Javascript
JavaScript性能优化之小知识总结
Nov 20 Javascript
一不小心就做错的JS闭包面试题
Nov 25 Javascript
AngularJS实用开发技巧(推荐)
Jul 13 Javascript
Angular2 PrimeNG分页模块学习
Jan 14 Javascript
Vue.js 中的 v-cloak 指令及使用详解
Nov 19 Javascript
解决vant中 tab栏遇到的坑 van-tabs
Nov 04 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使用ICQ网关发送手机短信
2013/10/30 PHP
PHP闭包实例解析
2014/09/08 PHP
javascript 网页跳转的方法
2008/12/24 Javascript
jQuery取得select选择的文本与值的示例
2013/12/09 Javascript
jquery进行数组遍历如何跳出当前的each循环
2014/06/05 Javascript
浅析Javascript ES6中的原生Promise
2016/08/25 Javascript
js 实现一些跨浏览器的事件方法详解及实例
2016/10/27 Javascript
JS实现的几个常用算法
2016/11/12 Javascript
前端js弹出框组件使用方法
2020/08/24 Javascript
微信小程序 数据封装,参数传值等经验分享
2017/01/09 Javascript
Javascript同时声明一连串(多个)变量的方法
2017/01/23 Javascript
BootStrap Datetimepicker 汉化的实现代码
2017/02/10 Javascript
JavaScript 实现自己的安卓手机自动化工具脚本(推荐)
2020/05/13 Javascript
vue结合el-upload实现腾讯云视频上传功能
2020/07/01 Javascript
python UNIX_TIMESTAMP时间处理方法分析
2016/04/18 Python
python目录与文件名操作例子
2016/08/28 Python
定制FileField中的上传文件名称实例
2017/08/23 Python
Python跳出多重循环的方法示例
2019/07/03 Python
Flask框架单例模式实现方法详解
2019/07/31 Python
python如何实现复制目录到指定目录
2020/02/13 Python
VSCODE配置Markdown及Markdown基础语法详解
2021/01/19 Python
CSS实现聊天气泡效果
2020/04/26 HTML / CSS
如何客观的进行自我评价
2013/12/17 职场文书
打造完美自荐信
2014/01/24 职场文书
六一儿童节演讲稿
2014/05/23 职场文书
工地门卫岗位职责范本
2014/07/01 职场文书
巾帼志愿者活动方案
2014/08/17 职场文书
2014年重阳节敬老活动方案
2014/09/16 职场文书
客户答谢会致辞
2015/01/20 职场文书
行政助理岗位职责
2015/02/10 职场文书
《从现在开始》教学反思
2016/02/16 职场文书
go:垃圾回收GC触发条件详解
2021/04/24 Golang
golang 实现两个结构体复制字段
2021/04/28 Golang
关于React Native使用axios进行网络请求的方法
2021/08/02 Javascript
游戏《东方异文石:爱亚利亚黎明》正式版发布
2022/04/03 其他游戏
Win10开机修复磁盘错误怎么跳过?Win10关闭开机磁盘检查的方法
2022/09/23 数码科技