[JS]Map和Set

Map 
是一个带键的数据项的集合,就像一个 Object 一样。 但是它们最大的差别是 Map 允许任何类型的键(key)。
 
它的方法和属性如下:
 
    new Map() - 创建 map。
      map.set(key, value) - 根据键存储值。
      map.get(key) - 根据键来返回值,如果 map 中不存在对应的 key,则返回 undefined。
      map.has(key) - 如果 key 存在则返回 true,否则返回 false。
      map.delete(key) - 删除指定键的值。
      map.clear() - 清空 map。
      map.size - 返回当前元素个数。
 
 1 let map = new Map();
 2 
 3 map.set('1', 'str1');   // 字符串键
 4 map.set(1, 'num1');     // 数字键
 5 map.set(true, 'bool1'); // 布尔值键
 6 
 7 // 普通的 Object 会将键转化为字符串
 8 // Map 则会保留键的类型,所以下面这两个结果不同:
 9 console.log(map.get(1)); // 'num1'
10 console.log(map.get('1')); // 'str1'
11 console.log(map.size); // 3
12 
13 // 使用对象作为键是 Map 最值得注意和重要的功能之一。
14 
15 // 可以链式调用
16 map.set('1', 'str1')
17       .set(1, 'num1')
18       .set(true, 'bool1');

 

如果要在 map 里使用循环,可以使用以下三个方法:
  
        map.keys() - 遍历并返回所有的键(returns an iterable for keys),
        map.values() - 遍历并返回所有的值(returns an iterable for values),
        map.entries() - 遍历并返回所有的实体(returns an iterable for entries)[key, value],for..of 在默认情况下使用的就是这个。
 
 1 let recipeMap = new Map([
 2       ['cucumber', 500],
 3       ['tomatoes', 350],
 4       ['onion', 50]
 5     ]);
 6 
 7     // 遍历所有的键(vegetables)
 8     for (let vegetable of recipeMap.keys()) {
 9       console.log(vegetable); // cucumber, tomatoes, onion
10     }
11 
12     // 遍历所有的值(amounts)
13     for (let amount of recipeMap.values()) {
14       console.log(amount); // 500, 350, 50
15     }
16 
17     // 遍历所有的实体 [key, value]
18     for (let entry of recipeMap) { // 与 recipeMap.entries() 相同
19       console.log(entry); // cucumber,500 (and so on)
20     }

 

当创建一个 Map 后,我们可以传入一个带有键值对的数组(或其它可迭代对象)来进行初始化
1 // 键值对 [key, value] 数组
2 let map = new Map([
3       ['1', 'str1'],
4       [1, 'num1'],
5       [true, 'bool1']
6     ]);
7 
8 console.log(map.get('1')); // str1

 

如果我们想从一个已有的普通对象(plain object)来创建一个 Map,那么我们可以使用内建方法 Object.entries(obj),该返回对象的键/值对数组,该数组格式完全按照 Map 所需的格式。
1 let obj = {
2       name: "John",
3       age: 30
4     };
5 
6 let map = new Map(Object.entries(obj));
7 
8 console.log(map.get('name')); // John

 

Map 也可以转为普通对象。
1 let map = new Map();
2     map.set('banana', 1);
3     map.set('orange', 2);
4     map.set('meat', 4);
5 
6 // let obj = Object.fromEntries(map.entries()); // 创建一个普通对象
7 let obj = Object.fromEntries(map); // 省掉 .entries()

 

Set
Set 是一个特殊的类型集合 - “值的集合”(没有键),它的每一个值只能出现一次。
 
它有以下方法:
 
    new Set(iterable) - 创建一个 set,如果提供了一个 iterable 对象(通常是数组),将会从数组里面复制值到 set 中。
      set.add(value) - 添加一个值,返回 set 本身
      set.delete(value) - 删除值,如果 value 在这个方法调用的时候存在则返回 true ,否则返回 false。
      set.has(value) - 如果 value 在 set 中,返回 true,否则返回 false。
      set.clear() - 清空 set。
      set.size - 返回元素个数
 
它的主要特点是,重复使用同一个值调用 set.add(value) 并不会发生什么改变。这就是 Set 里面的每一个值只出现一次的原因。
 
 1 let set = new Set();
 2 
 3 let john = { name: "John" };
 4 let pete = { name: "Pete" };
 5 let mary = { name: "Mary" };
 6 
 7 // visits,一些访客来访好几次
 8 set.add(john);
 9 set.add(pete);
10 set.add(mary);
11 set.add(john);
12 set.add(mary);
13 
14 // set 只保留不重复的值
15 alert(set.size); // 3
16 
17 for (let user of set) {
18     alert(user.name); // John(然后 Pete 和 Mary)
19 }
20 
21 // 可以使用 for..of 或 forEach 来遍历 Set
22 let set = new Set(["oranges", "apples", "bananas"]);
23 
24 for (let value of set) alert(value);
25 
26   // 与 forEach 相同:
27   set.forEach((value, valueAgain, set) => {
28     alert(value);
29   });

 

forEach 的回调函数有三个参数,是为了与 Map 兼容。确实有些奇怪,但是这对在特定情况下轻松地用 Set 代替 Map 很有帮助,反之亦然。
    Map 中用于迭代的方法在 Set 中也同样支持:

    set.keys() - 遍历并返回所有的值(returns an iterable object for values),
    set.values() - 与 set.keys() 作用相同,这是为了兼容 Map,
    set.entries() - 遍历并返回所有的实体(returns an iterable object for entries)[value, value],它的存在也是为了兼容 Map。
 
 
使用Set实现数组去重真的是太方便了:
 1 function unique(arr) {
 2       let set = new Set(arr);
 3       return set;
 4 }
 5 
 6 let values = ["Hare", "Krishna", "Hare", "Krishna",
 7    "Krishna", "Krishna", "Hare", "Hare", ":-O"
 8 ];
 9 
10 console.log(unique(values)); // ["Hare", "Krishna", ":-O"]

 

posted @ 2020-03-03 00:01  冯风风  阅读(578)  评论(0编辑  收藏  举报