JS常用方法整理
Map 和 Set 用法详解 一、Map(映射) Map 是一个带键的数据项的集合,与 Object 类似,但允许任何类型的键 。
1. 创建和基本操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 let map = new Map (); map.set ('name' , '张三' ); map.set (1 , 'number one' ); map.set (true , 'boolean' );console .log (map.get ('name' )); console .log (map.get (1 )); console .log (map.has ('name' )); console .log (map.has ('age' )); map.delete ('name' );console .log (map.size ); map.clear ();
2. 链式调用 set 方法返回 map 本身,可以链式调用:
1 2 3 4 let map = new Map (); map.set ('a' , 1 ) .set ('b' , 2 ) .set ('c' , 3 );
3. 对象作为键(重要特性) 1 2 3 4 5 6 7 8 9 10 11 12 13 let john = { name : 'John' };let ben = { name : 'Ben' };let visitsCountMap = new Map (); visitsCountMap.set (john, 123 ); visitsCountMap.set (ben, 456 );console .log (visitsCountMap.get (john)); console .log (visitsCountMap.get (ben));
4. Map 迭代 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 let recipeMap = new Map ([ ['cucumber' , 500 ], ['tomatoes' , 350 ], ['onion' , 50 ] ]);for (let vegetable of recipeMap.keys ()) { console .log (vegetable); }for (let amount of recipeMap.values ()) { console .log (amount); }for (let entry of recipeMap.entries ()) { console .log (entry); }for (let [key, value] of recipeMap) { console .log (`${key} : ${value} ` ); } recipeMap.forEach ((value, key, map ) => { console .log (`${key} : ${value} ` ); });
重要:Map 保持插入顺序 ,迭代顺序与插入顺序相同。
5. 从对象创建 Map 1 2 3 4 5 6 7 8 9 10 let obj = { name : 'John' , age : 30 };let map = new Map (Object .entries (obj));console .log (map.get ('name' )); console .log (map.get ('age' ));
6. 从 Map 创建对象 1 2 3 4 5 6 7 8 9 10 11 12 let map = new Map ([ ['banana' , 1 ], ['orange' , 2 ], ['meat' , 4 ] ]);let obj = Object .fromEntries (map.entries ());let obj2 = Object .fromEntries (map);console .log (obj);
7. Map 与 Object 对比
特性
Map
Object
键类型
任意类型
字符串/Symbol
键顺序
保持插入顺序
不保证顺序
大小
size 属性
需手动计算
迭代
直接可迭代
需 Object.keys()
性能
频繁增删时更好
字面量创建更方便
二、Set(集合) Set 是值的集合 ,每个值只能出现一次(自动去重)。
1. 创建和基本操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 let set = new Set (); set.add (1 ); set.add (2 ); set.add (3 ); set.add (1 ); console .log (set); console .log (set.has (1 )); console .log (set.has (5 )); set.delete (2 );console .log (set.size ); set.clear ();
2. 从数组创建(去重) 1 2 3 4 5 6 7 8 9 let arr = [1 , 2 , 2 , 3 , 3 , 3 , 4 , 4 , 4 , 4 ];let uniqueSet = new Set (arr);let uniqueArr = [...uniqueSet];console .log (uniqueArr); let unique = [...new Set (arr)];
3. Set 迭代 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let set = new Set (['apple' , 'orange' , 'banana' ]);for (let value of set) { console .log (value); } set.forEach ((value, valueAgain, set ) => { console .log (value); }); set.keys (); set.values (); set.entries ();
4. Set 常见用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function unique (arr ) { return [...new Set (arr)]; }let str = 'aabbccdd' ;let uniqueStr = [...new Set (str)].join ('' ); let a = new Set ([1 , 2 , 3 ]);let b = new Set ([2 , 3 , 4 ]);let intersection = new Set ([...a].filter (x => b.has (x)));console .log ([...intersection]); let union = new Set ([...a, ...b]);console .log ([...union]); let difference = new Set ([...a].filter (x => !b.has (x)));console .log ([...difference]);
三、WeakMap 和 WeakSet WeakMap
键必须是对象
键是弱引用,不阻止垃圾回收
不可迭代,没有 size、keys()、values()、entries() 方法
只有 get、set、has、delete 方法
1 2 3 4 5 6 7 8 let weakMap = new WeakMap ();let obj = { name : 'test' }; weakMap.set (obj, 'some value' );console .log (weakMap.get (obj)); obj = null ;
应用场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 let userCache = new WeakMap ();function process (user ) { if (!userCache.has (user)) { let result = ; userCache.set (user, result); } return userCache.get (user); }const privateData = new WeakMap ();class Person { constructor (name ) { privateData.set (this , { name }); } getName ( ) { return privateData.get (this ).name ; } }
WeakSet
值必须是对象
值是弱引用
不可迭代
只有 add、has、delete 方法
1 2 3 4 5 6 7 8 let weakSet = new WeakSet ();let user = { name : 'John' }; weakSet.add (user);console .log (weakSet.has (user)); user = null ;
应用场景:
1 2 3 4 5 6 7 8 9 10 let visitedSet = new WeakSet ();function visit (user ) { visitedSet.add (user); }function isVisited (user ) { return visitedSet.has (user); }
四、方法总结 Map 方法
方法/属性
说明
new Map([iterable])
创建 map
map.set(key, value)
存储键值对,返回 map
map.get(key)
获取值,不存在返回 undefined
map.has(key)
检查键是否存在
map.delete(key)
删除指定键
map.clear()
清空 map
map.size
元素个数
map.keys()
返回键的可迭代对象
map.values()
返回值的可迭代对象
map.entries()
返回 [key, value] 的可迭代对象
map.forEach(fn)
遍历
Set 方法
方法/属性
说明
new Set([iterable])
创建 set
set.add(value)
添加值,返回 set
set.has(value)
检查值是否存在
set.delete(value)
删除值
set.clear()
清空 set
set.size
元素个数
set.keys()
返回值的可迭代对象
set.values()
同 keys()
set.entries()
返回 [value, value] 的可迭代对象
set.forEach(fn)
遍历
五、实用示例 统计词频 1 2 3 4 5 6 7 8 9 10 11 12 13 function wordCount (str ) { let map = new Map (); let words = str.toLowerCase ().match (/\w+/g ) || []; for (let word of words) { map.set (word, (map.get (word) || 0 ) + 1 ); } return map; }let counts = wordCount ('Hello world hello' );console .log (counts);
过滤数组中的唯一元素 1 2 3 4 5 6 function unique (arr ) { return Array .from (new Set (arr)); }let values = ['Hare' , 'Krishna' , 'Hare' , 'Krishna' , 'Krishna' ];console .log (unique (values));
过滤字谜(anagrams) 1 2 3 4 5 6 7 8 9 10 11 12 13 function aclean (arr ) { let map = new Map (); for (let word of arr) { let sorted = word.toLowerCase ().split ('' ).sort ().join ('' ); map.set (sorted, word); } return Array .from (map.values ()); }let arr = ['nap' , 'teachers' , 'cheaters' , 'PAN' , 'ear' , 'era' , 'hectares' ];console .log (aclean (arr));
Map.keys() 转数组 1 2 3 4 5 6 7 8 9 10 11 let map = new Map ([ ['name' , 'John' ], ['age' , 30 ] ]);let keys = Array .from (map.keys ());let keys2 = [...map.keys ()]; keys.push ('more' );
参考资料