欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈es6 javascript的map数据结构

程序员文章站 2022-12-08 12:38:43
本文介绍了es6 javascript的map数据结构,分享给大家,具体如下: map 结构的目的和基本用法 javascript 的对象( object),...

本文介绍了es6 javascript的map数据结构,分享给大家,具体如下:

map 结构的目的和基本用法

javascript 的对象( object), 本质上是键值对的集合( hash 结构), 但是传统上只能用字符串当作键。 这给它的使用带来了很大的限制。

var data = {}; 
var element = document.getelementbyid('mydiv'); 
data[element] = 'metadata'; 
data['[object htmldivelement]'] // "metadata" 

上面代码原意是将一个 dom 节点作为对象data的键, 但是由于对象只接受字符串作为键名, 所以element被自动转为字符串[object htmldivelement]。

为了解决这个问题, es6 提供了 map 数据结构。 它类似于对象, 也是键值对的集合, 但是“ 键” 的范围不限于字符串, 各种类型的值( 包括对象) 都可以当作键。 也就是说, object 结构提供了“ 字符串— 值” 的对应, map 结构提供了“ 值— 值” 的对应, 是一种更完善的 hash 结构实现。 如果你需要“ 键值对” 的数据结构, map 比 object 更合适。

var m = new map(); 
var o = { 
 p: 'hello world' 
}; 
m.set(o, 'content') 
m.get(o) // "content" 
m.has(o) // true 
m.delete(o) // true 
m.has(o) // false 

上面代码使用set方法, 将对象o当作m的一个键, 然后又使用get方法读取这个键, 接着使用delete方法删除了这个键。
作为构造函数, map 也可以接受一个数组作为参数。 该数组的成员是一个个表示键值对的数组。

var map = new map([ 
 ['name', ' 张三 '], 
 ['title', 'author'] 
]); 
map.size // 2 
map.has('name') // true 
map.get('name') // " 张三 " 
map.has('title') // true 
map.get('title') // "author" 

上面代码在新建 map 实例时, 就指定了两个键name和title。

map 构造函数接受数组作为参数, 实际上执行的是下面的算法。

var items = [ 
 ['name', ' 张三 '], 
 ['title', 'author'] 
]; 
var map = new map(); 
items.foreach(([key, value]) => map.set(key, value)); 

下面的例子中, 字符串true和布尔值true是两个不同的键。

var m = new map([ 
 [true, 'foo'], 
 ['true', 'bar'] 
]); 
m.get(true) // 'foo' 
m.get('true') // 'bar' 

如果对同一个键多次赋值, 后面的值将覆盖前面的值。

let map = new map(); 
map 
 .set(1, 'aaa') 
 .set(1, 'bbb'); 
map.get(1) // "bbb" 

上面代码对键1连续赋值两次, 后一次的值覆盖前一次的值。

如果读取一个未知的键, 则返回undefined。

new map().get('asfddfsasadf') 
 // undefined 

注意, 只有对同一个对象的引用, map 结构才将其视为同一个键。 这一点要非常小心。

var map = new map(); 
map.set(['a'], 555); 
map.get(['a']) // undefined 

上面代码的set和get方法, 表面是针对同一个键, 但实际上这是两个值, 内存地址是不一样的, 因此get方法无法读取该键, 返回undefined。

同理, 同样的值的两个实例, 在 map 结构中被视为两个键。

var map = new map(); 
var k1 = ['a']; 
var k2 = ['a']; 
map 
 .set(k1, 111) 
 .set(k2, 222); 
map.get(k1) // 111 
map.get(k2) // 222 

上面代码中, 变量k1和k2的值是一样的, 但是它们在 map 结构中被视为两个键。

由上可知, map 的键实际上是跟内存地址绑定的, 只要内存地址不一样, 就视为两个键。 这就解决了同名属性碰撞( *) 的问题, 我们扩展别人的库的时候, 如果使用对象作为键名, 就不用担心自己的属性与原作者的属性同名。

如果 map 的键是一个简单类型的值( 数字、 字符串、 布尔值), 则只要两个值严格相等, map 将其视为一个键, 包括0和 - 0。 另外, 虽然nan不严格相等于自身, 但 map 将其视为同一个键。

let map = new map(); 
map.set(nan, 123); 
map.get(nan) // 123 
map.set(-0, 123); 
map.get(+0) // 123 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。