你的哈希表写法可能并不对

简介: 欢迎关注我:前端西瓜哥

大家好,我是前端西瓜哥。

以前我在 JS 中写字符串哈希表,是直接用对象字面量的形式来初始化的。

const map = {};
map['a'] = 1;
const key = map['a'];

然后我看了下 Vue2 源码中哈希表的写法。

const map = Object.create(null);

咋一看,觉得不太优雅,怎么这么臭长臭长的。再认真思考了一下,西瓜哥我才发现了盲点。

二者的区别涉及到了 JS 中访问对象属性的机制:原型链

原型链

JS 中创建对象时,会给该对象添加一个指向某个对象的内置属性 [[Prototype]],这个被指向的对象就被称为原型对象。然后原型对象自身也有内置属性 [[Prototype]],层层嵌套,直到为 null 结束,形成了一个原型链

当我们访问对象属性时,如果当前对象中不存在,就会找它的原型对象里找同名属性,如果找到就返回它;如果找不到,继续向上,直到 null 为止还是找不到,才返回 undefined。

更多原型链的解读可以看我的一篇文章:《用原型链的方式实现一个 JS 继承

字面量对象写法({})的原型链是这样的:

map -> Object.prototype -> null

即使 map 为空,在访问一些特定的属性时就会拿到一些特定的 key 时(比如 toString),会因为原型链的关系,拿到 Object.prototype 的属性,导致无法得到预期的 undefined 值。

因为就只有这几个特殊的 key 值,所以不容易难命中,平时还算运行良好,但一旦出了问题,如果你不知道这个知识点,排查起来还是比较困难的。

至于 Object.create(null) ,它能够创建一个空对象,并将 [[prototype]] 属性值设置为传入对象,这里是 null。

它的原型链是长这样:

map -> null

map 对象找不到属性,去找原型对象,结果原型对象直接就是 null,没有中间商赚差价,我们就拿到预期的 undefined。

ES6 新增的 Map 数据结构

其实我们也可以用 ES6 新增的 Map 数据结构来实现哈希表,但我想说它太笨重了。

如果只是简单地使用 key 为字符串类型的哈希表,只是读写键值对,我还是更倾向于用普通对象哈希表,不为什么,代码更短一点。

// Map 对象写法
map.set(k, v);
map.get(k);
// 普通对象写法
map[k] = v;
map[k];

结尾

因为 JS 对象访问属性会追溯原型链的特性,不建议使用字面量对象的写法来实现哈希表。

正确的方式是使用 Object.assgin(null) 或者更重一点的 Map 数据结构。

我是前端西瓜哥,一名喜欢分享的前端开发,欢迎关注我。

相关文章
|
4月前
|
存储 C++ 索引
哈希表、集合、映射
哈希表、集合、映射
|
4月前
一道题学会如何使用哈希表
一道题学会如何使用哈希表
|
11月前
|
存储 算法 Serverless
|
4月前
|
存储 算法 Java
算法系列--哈希表
算法系列--哈希表
28 0
|
算法 容器
哈希表的简单模拟实现
哈希表的简单模拟实现
47 0
|
算法 索引
哈希表— —链式实现
哈希表— —链式实现
|
存储 数据库
第 9 章 哈希表
散列表(Hash table, 也叫哈希表) ,是根据关键码值(Key value)而直接进行访问的数据结构。
82 1
|
存储 SQL 关系型数据库
MySql索引详解-各种索引的定义与区别和应用
什么是索引?索引的作用,有无索引的区别。
187 0
MySql索引详解-各种索引的定义与区别和应用
|
存储 Java Serverless
哈希表(重要)
哈希表(重要)
146 0
哈希表(重要)