JavaScript的Map和Set以及iterable
Map
JavaScript的默认对象可以视为其他语言的dictionary和map,键值对。
但它的键必须为字符串,为了解决这个问题ES6引入了数据类型Map。
Map也是一组键值对的结构,具有极快的查找速度。
用Map实现通过名字快速查询成绩:
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]); m.get('Michael'); // 95
好处是无论数据有多大,查询速度不会变慢。另一种写法;
var m = new Map(); // 空Map m.set('Adam', 67); // 添加新的key-value m.set('Bob', 59); m.has('Adam'); // 是否存在key 'Adam': true m.get('Adam'); // 67 m.delete('Adam'); // 删除key 'Adam' m.get('Adam'); // undefined
同样的key会被后面的冲掉。
set
Set不存储value,用于过滤重复的值;
var s = new Set([1, 2, 3, 3, '3']); s; // Set {1, 2, 3, "3"} s.add(4); s.delete(3); s.add(4);
可以重复添加但不会有效。
iterable
遍历Array可以使用下标循环,但Map和Set不能。为了统一集合类型。ES6引入了iterable类型,前面三个都属于此类型。
且具有iterable类型的集合可以通过新的for .. of循环来遍历;
for .. in循环遍历的实际上是对象的属性名称。Array数组实际上也是一个对象。每个元素的索引被视为属性。
手动为Array添加属性再循环,可以得到意想不到的结果;
var a = ['A', 'B', 'C']; a.name = 'Hello'; for (var x in a) { console.log(x); // '0', '1', '2', 'name' } for (var x of a) { console.log(x); // 'A', 'B', 'C' }
for .. in循环把name包括了,但Array的length属性没包括。
for .. of循环只包含集合本身元素。
更好的方式是使用iterable内置方法forEach方法,它接收一个函数,每次迭代就自动回调该函数;
var a = ['A', 'B', 'C']; a.forEach(function (element, index, array) { // element: 指向当前元素的值 // index: 指向当前索引 // array: 指向Array对象本身 console.log(element + ', index = ' + index); }); var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); m.forEach(function (value, key, map) { console.log(value); }); var s = new Set(['A', 'B', 'C']); s.forEach(function (element, sameElement, set) { console.log(element); // set没有索引因此前两个参数都是元素本身 });