ES6 提供了 Map 数据结构。是键值对的集合,Map类似于对象,但是其键的范围不限于对象的字符串,各种类型的值(包括对象)都可以当作键。
一.Map数据结构
1.基本定义
- ① Map数据结构的定义
//例一 创建一个的Map空集合,使用常规的set,get,has,delete方法操作 const m = new Map(); const o = {p: 'Hello World'}; m.set(o, 'content') m.get(o) // "content" m.has(o) // true m.delete(o) // true m.has(o) // false //例二 使用嵌套数组初始化map对象 const map = new Map([ ['name', 'Joey'], ['title', 'Author'] ]); map.size // 2 map.has('name') // true map.get('name') // "张三" map.has('title') // true map.get('title') // "Author" // 例三 任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构,都可以当作Map构造函数的参数。这就是说,Set和Map都可以用来生成新的 Map。 const set = new Set([ ['foo', 1], ['bar', 2] ]); const m1 = new Map(set); m1.get('foo') // 1 const m2 = new Map([['baz', 3]]); const m3 = new Map(m2); m3.get('baz') // 3
2.Map数据结构的特性
-
① Map数据结构也是键值对的集合,与对象结构类似,但是对象结构只能使用字符串或者Symbol当做键,而Map的键可以是随意的值或者结构。
es5中对象作为key值,自动转换为字符串存储 const data = {}; const element = document.getElementById('myDiv'); data[element] = 'metadata'; data['[object HTMLDivElement]'] // "metadata"
-
② Map数据结构key的唯一性,多次赋值,后面的值将覆盖前面的值。
const map = new Map(); map .set(1, 'aaa') .set(1, 'bbb'); map.get(1) // "bbb"
-
③ 若读取的是一个未知的键,则返回
undefined
new Map().get('asfddfsasadf') // undefined
-
④ 若map结构中key引用的不是同一地址的对象,则视为2个键。
//一 const map = new Map(); map.set(['a'], 555); map.get(['a']) // undefined //二 const map = new Map(); const k1 = ['a']; const k2 = ['a']; map .set(k1, 111) .set(k2, 222); map.get(k1) // 111 map.get(k2) // 222
-
⑤ 针对于基础类型
0
,-0
,+0
为同一值;undefined
与null
不为同一值;虽然NaN不严格相等于自身,但 Map 将其视为同一个键。let map = new Map(); map.set(-0, 123); map.get(+0) // 123 map.set(true, 1); map.set('true', 2); map.get(true) // 1 map.set(undefined, 3); map.set(null, 4); map.get(undefined) // 3 map.set(NaN, 123); map.get(NaN) // 123
3.Map结构的常规方法
-
Map
size 属性
:返回 Map 结构的成员总数。
Map.prototype.set(key, value)
:set方法设置键名key对应的键值为value,然后返回整个 Map 结构。因此可以采用链式写法。
Map.prototype.get(key)
:get方法读取key对应的键值,如果找不到key,返回undefined。
Map.prototype.has(key)
:has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
Map.prototype.delete(key)
:delete方法删除某个键,返回true。如果删除失败,返回false。
Map.prototype.clear()
:clear方法清除所有成员,没有返回值。 -
范例
//1.size const map = new Map(); map.set('foo', true); map.set('bar', false); map.size // 2 //2.set let map = new Map() .set(1, 'a') .set(2, 'b') .set(3, 'c'); //3.get const m = new Map(); const hello = function() {console.log('hello');}; m.set(hello, 'Hello ES6!') // 键是函数 m.get(hello) // Hello ES6! //4.has const m = new Map(); m.set('edition', 6); m.set(262, 'standard'); m.set(undefined, 'nah'); m.has('edition') // true m.has('years') // false m.has(262) // true m.has(undefined) // true //5.delete const m = new Map(); m.set(undefined, 'nah'); m.has(undefined) // true m.delete(undefined) m.has(undefined) // false //6.clear let map = new Map(); map.set('foo', true); map.set('bar', false); map.size // 2 map.clear() map.size // 0
4.Map数据结构的遍历
-
Map 结构的实例有四个遍历方法
Map.prototype.keys()
:返回键名的遍历器
Map.prototype.values()
:返回键值的遍历器
Map.prototype.entries()
:返回键值对的遍历器
Map.prototype.forEach()
:使用回调函数遍历每个成员 -
keys(),values(),entries()遍历范例
//一 keys const map = new Map([ ['F', 'no'], ['T', 'yes'], ]); for (let key of map.keys()) { console.log(key); } // "F" // "T" //二 values for (let value of map.values()) { console.log(value); } // "no" // "yes" //三 entries for (let item of map.entries()) { console.log(item[0], item[1]); } // "F" "no" // "T" "yes" // 或者 for (let [key, value] of map.entries()) { console.log(key, value); } // "F" "no" // "T" "yes" // 等同于使用map.entries() 因为 Map 结构的默认遍历器接口(Symbol.iterator属性),就是entries方法。 for (let [key, value] of map) { console.log(key, value); } // "F" "no" // "T" "yes" map[Symbol.iterator] === map.entries // true
-
forEach使用回调函数的方式进行遍历,参数依次是value值,key值,map对象
map.forEach(function(value, key, map) { console.log("Key: %s, Value: %s", key, value); });
-
forEach方法还可以接受第二个参数,用来绑定this。
//下面代码中,forEach方法的回调函数的this,就指向reporter。 const reporter = { report: function(key, value) { console.log("Key: %s, Value: %s", key, value); } }; map.forEach(function(value, key, map) { this.report(key, value); //this为{report: ƒ} }, reporter);