Set和Map主要的应用场景在于数据重组和数据储存;
Set是一种叫做集合的数据结构,Map是一种叫做字典的数据结构。
集合(Set)
ES6 新增的一种新的数据结构,类似于数组,但成员是唯一且无序的,没有重复的值。
Set 本身是一种构造函数,用来生成Set数据结构。
new Set([iterable]);
举个例子:
const s = new Set ();
[1, 2, 3, 4, 3, 2, 1]. forEach (x => s.add(x));
for (let i of s) {console.log(i); /*1 2 3 4*/}
// 去重数组的重复对象
let arr = [1, 2, 3, 2, 1, 1];
[... new Set(arr)] // [1, 2, 3];
Set 对象允许储存任何类型的唯一值,无论是原始值或者是对象引用。
向Set加值时不会发生类型转换,如5和"5"是两个不同的值。Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于===,区别是Set 认为NaN等于自身,而===认为NaN不等于自身。
let set = new Set ();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
console.log(set) // Set {NaN}
let set1 = new Set ()
set1.add (5);
set1.add ('5');
console.log ([...set1]); // [5, "5"]
- Set 实例属性
- constructor: 构造函数
- size:元素数量
let set = new Set ([1, 2, 3, 2, 1]);
console.log (set. length); // undefined
console.log (set. size); // 3
- Set 实例方法
操作方法
-
- add(value):新增,相当于 array里的push
- delete(value):存在即删除集合中value
- has(value):判断集合中是否存在 value
- clear():清空集合
let set = new Set ();
set.add (1). add (2). add (1);
set.has (1); // true
set.has (3); // false
set. delete (1);
set.has (1); // false
遍历方法(遍历顺序为插入顺序)
-
- keys():返回一个包含集合中所有键的迭代器;
- values():返回一个包含集合中所有值得迭代器;
- entries():返回一个包含Set对象中所有元素键值对迭代器
- forEach(callback, thisArg):对集合成员执行callback操作,如提供thisArg参数,回调中的this会是这个参数,没有返回值。
let set = new Set ([1, 2, 3]);
console.log (set. keys ()); // SetIterator {1, 2, 3}
console.log (set. values ()); // SetIterator {1, 2, 3}
console.log (set. entries ()); // SetIterator {1, 2, 3}
for (let item of set. keys ()) {
console.log(item);
} // 1 2 3
for (let item of set. entries ()) {
console.log(item);
} // [1, 1] [2, 2] [3, 3]
set. forEach ((value, key) => {
console.log (key + ':' + value)
}) // 1:1 2:2 3:3
console.log ([...set]) // [1, 2, 3]
Set可以使用 map、filter 方法实现交集、并集、差集:
let set1 = new Set ([1, 2, 3])
let set2 = new Set ([4, 3, 2])
let intersect = new Set ([...set1]. filter (value => set2.has(value)))
let union = new Set ([...set1, ...set2])
let difference = new Set ([...set1]. filter (value =>! set2.has(value)))
console.log(intersect) // Set {2, 3}
console.log(union) // Set {1, 2, 3, 4}
console.log(difference) // Set {1}
字典(Map)
- 集合与字典的区别:
- 相同:集合、字典 可以储存不重复的值;
- 不同:集合以[v, v]形式储存元素,字典以[k, v]形式储存。
- Map的创建:
任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作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
Map的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。如果读取一个未知的键,则返回undefined。
const map = new Map ();
map.set(['a'], 555);
map.get(['a']) // undefined
如果Map键是简单类型(数字、字符串、布尔值),则只要严格相等(===),Map就将其视为一个键。比如0和-0是一个键,true和'true'是两个键。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的属性:
- constructor: 构造函数;
- size:元素数量。
- Map的方法:
操作方法
-
-
- set(key, value):向字典中添加新元素;
- get(key):通过键查找特定的数值并返回;
- has(key):判断字典中是否存在键key;
- delete(key):通过键 key 从字典中移除对应的数据;
- clear():将这个字典中的所有元素删除。
-
遍历方法
-
-
- Keys():将字典中包含的所有键名以迭代器形式返回;
- values():将字典中包含的所有数值以迭代器形式返回;
- entries():返回所有成员的迭代器;
- forEach():遍历字典的所有成员。
-
const map = new Map ([
['name', 'An'], ['des', 'JS']
]);
map. entries () ;// MapIterator{"name" => "An", "des" => "JS"}
map. keys (); // MapIterator {"name", "des"}
Map 结构转为数组结构,比较快速的方法是使用扩展运算符(...)。
对于 forEach 的例子:
const reporter = {
report: function (key, value) {
console.log ("Key: %s, Value: %s", key, value);
}
};
let map = new Map ([
['name', 'An'], ['des', 'JS']
]);
map. forEach (function (value, key, map) {
this. report (key, value);
}, reporter);
// Key: name, Value: An
// Key: des, Value: JS
- 与其他数据结构的相互转换
- Map 转 Array:
const map = new Map ([[1, 1], [2, 2], [3, 3]]);
console.log ([...map]); // [[1, 1], [2, 2], [3, 3]]
-
- Array 转 Map:
const map = new Map ([[1, 1], [2, 2], [3, 3]]);
console.log(map); // Map {1 => 1, 2 => 2, 3 => 3}
-
- Map 转 Object:
Object的键名都为字符串,而Map的键名为对象,所以转换的时候会把非字符串键名转换为字符串键名。
function mapToObj(map) {
let obj = Object.create(null);
for (let [key, value] of map) {
obj[key] = value;
}
return obj;
}
const map = new Map (). set ('name', 'An'). set ('des', 'JS');
mapToObj(map); // {name: "An", des: "JS"}
-
- Object 转 Map
function objToMap(obj) {
let map = new Map ();
for (let key of Object.keys(obj)) {
map.set (key, obj[key]);
}
return map;
}
objToMap ({'name': 'An', 'des': 'JS'});
// Map {"name" => "An", "des" => "JS"}
-
- Map 转 JSON
function mapToJson(map) {
return JSON.stringify([...map]);
}
let map = new Map (). set ('name', 'An'). set ('des', 'JS');
mapToJson(map); // [["name","An"], ["des","JS"]]
-
- JSON 转 Map
function jsonToStrMap(jsonStr) {
return objToMap (JSON.parse(jsonStr));
}
jsonToStrMap ('{"name": "An", "des": "JS"}');
// Map {"name" => "An", "des" => "JS"}