ES6学习笔记 —— Set与Map
Set 对象
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
Set 中的特殊值
Set 对象存储的值总是唯一的,所以需要判断两个值是否恒等。有几个特殊值需要特殊对待:
- +0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复;
- undefined 与 undefined 是恒等的,所以不重复;
- NaN 与 NaN 是不恒等的,但是在 Set 中只能存一个,不重复。
Set声明
1 | const set = new Set() |
Set属性
- size:返回 Set 对象中值的数量
Set方法
- add(value): 在Set对象尾部添加一个元素,返回该Set对象。
- delete(value): 移除Set的中与这个值相等的元素,有则返回true,无则返回false。
- clear(): 清楚Set的所有元素。
- has(value): 是否存在这个值,如果存在为 true,否则为false。
- keys():返回键名的遍历器。
- values():返回键值的遍历器。
- entries():返回键值对的遍历器。
- forEach():使用回调函数遍历每个成员。
Set方法使用:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | let mySet = new Set() //add() mySet.add( '1' ) mySet.add(1) console.log(mySet) // Set(2) {1, "1"} //size console.log(mySet.size) // 2 //delete() mySet. delete ( '1' ) console.log(mySet) // Set(1) {1} //has() console.log(mySet.has(1)) // true console.log(mySet.has(2)) // false //clear() mySet.clear() console.log(mySet) // Set(0) {} let arr = [{id: 1}, {id: 2}, {id: 3}] let mySet1 = new Set(arr) // keys() for ( let key of mySet1.keys()) { console.log( 'key:' , key); // key:{id: 1} key:{id: 2} key:{id: 3} } //values() for ( let key of mySet1.values()) { console.log( 'values:' , key); // values:{id: 1} values:{id: 2} values:{id: 3} } //entries() for ( let data of mySet1.entries()) { console.log( 'entries:' , data); // entries:[{id: 1},{id: 1}] entries:[{id: 2},{id: 2}] entries:[{id: 3},{id: 3}] } //forEach mySet1.forEach((item) => { console.log( 'forEach:' , item) // forEach:{id: 1} forEach:{id: 2} forEach:{id: 3} }); |
Set对象应用
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 | // 数组去重 var mySet = new Set([1, 2, 3, 4, 4]); [...mySet]; // [1, 2, 3, 4] // 字符串去重 [... new Set( 'ababbc' )].join( '' ) // "abc" let a = new Set([1, 2, 3]) let b = new Set([2, 4, 3]) //并集 let union = new Set([...a, ...b])) // {1, 2, 3, 4} //交集 let intersect = new Set([...a].filter(x => b.has(x))) // {2, 3} // 差集 // (a 相对于 b 的)差集 let difference = new Set([...a].filter(x => !b.has(x))) // {1} // 映射 // 方法一 let set = new Set([1, 2, 3]); set = new Set([...set].map(val => val * 2)); // set的值是2, 4, 6 // 方法二 let set = new Set([1, 2, 3]); set = new Set(Array.from(set, val => val * 2)); // set的值是2, 4, 6 |
Map 对象
Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
Map属性
- size:返回 Map 结构的成员总数。
Map方法
- set(key,value): 设置键名
key
对应的键值为value
的键值对,若key已存在,更新键值。 - get(key): 返回key对应的值。
- delete(key): 移除Map的中与这个值相等的元素,有则返回true,无则返回false。
- clear(): 清除所有成员,没有返回值。
- has(key): 是否存在这个值,如果存在为 true,否则为false。
- keys():返回键名的遍历器。
- values():返回键值的遍历器。
- entries():返回所有成员的遍历器。
- forEach():遍历 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | let myMap = new Map() //set(key,value) myMap.set( 'a' , 1) myMap.set( 'b' , 2) console.log(myMap) // Map(2) {'a' => 1, 'b' => 2} //get(key) console.log(myMap.get( 'a' )) // 1 myMap.set( 'a' , 3) console.log(myMap.get( 'a' )) // 3 同一个键多次赋值,后面的值将覆盖前面的值。 //size console.log(myMap.size) // 2 //delete(key) myMap. delete ( 'a' ) // true console.log(myMap) // Map(1) {'b' => 2} //has(key) console.log(myMap.has( 'b' )) // true console.log(myMap.has(1)) // false //clear() myMap.clear() console.log(myMap) // Map(0) {} let arr = [[ 'a' , 1],[ 'b' , 2],[ 'c' , 3]] let myMap1 = new Map(arr) // keys() for ( let key of myMap1.keys()) { console.log( 'keys:' , key); // keys:a keys:b keys:c } //values() for ( let value of myMap1.values()) { console.log( 'values:' , value); // values:1 values:2 values:3 } //entries() for ( let data of myMap1.entries()) { console.log( 'entries:' , data); // entries:["a", 1] entries:["b", 2] entries:["c", 3] } //forEach myMap1.forEach((item) => { console.log( 'forEach:' ,item) // forEach:1 forEach:2 forEach:3 }); |
与其他数据结构的互相转换
(1)Map 转为数组
使用扩展运算符(...
)。
1 2 3 4 5 | const myMap = new Map() .set( true , 7) .set({foo: 3}, [ 'abc' ]); [...myMap] // [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ] |
(2)数组 转为 Map
将数组传入 Map 构造函数,就可以转为 Map。
1 2 3 4 | new Map([ [ true , 7], [{foo: 3}, [ 'abc' ]] ]) |
(3)Map 转为对象
如果所有 Map 的键都是字符串,它可以无损地转为对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 | function strMapToObj(strMap) { let obj = Object.create( null ); for ( let [k,v] of strMap) { obj[k] = v; } return obj; } const myMap = new Map() .set( 'yes' , true ) .set( 'no' , false ); strMapToObj(myMap) // { yes: true, no: false } |
如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。
(4)对象转为 Map
对象转为 Map 可以通过Object.entries()
。
1 2 | let obj = { "a" :1, "b" :2}; let map = new Map(Object.entries(obj)); |
此外,也可以自己实现一个转换函数。
1 2 3 4 5 6 7 8 9 10 | function objToStrMap(obj) { let strMap = new Map(); for ( let k of Object.keys(obj)) { strMap.set(k, obj[k]); } return strMap; } objToStrMap({yes: true , no: false }) // Map {"yes" => true, "no" => false} |
(5)Map 转为 JSON
Map 转为 JSON 要区分两种情况。一种情况是,Map 的键名都是字符串,这时可以选择转为对象 JSON。
1 2 3 4 5 6 7 | function strMapToJson(strMap) { return JSON.stringify(strMapToObj(strMap)); } let myMap = new Map().set( 'yes' , true ).set( 'no' , false ); strMapToJson(myMap) // '{"yes":true,"no":false}' |
另一种情况是,Map 的键名有非字符串,这时可以选择转为数组 JSON。
1 2 3 4 5 6 7 | function mapToArrayJson(map) { return JSON.stringify([...map]); } let myMap = new Map().set( true , 7).set({foo: 3}, [ 'abc' ]); mapToArrayJson(myMap) // '[[true,7],[{"foo":3},["abc"]]]' |
(6)JSON 转为 Map
JSON 转为 Map,正常情况下,所有键名都是字符串。
1 2 3 4 5 6 | function jsonToStrMap(jsonStr) { return objToStrMap(JSON.parse(jsonStr)); } jsonToStrMap( '{"yes": true, "no": false}' ) // Map {'yes' => true, 'no' => false} |
但是,有一种特殊情况,整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组。这时,它可以一一对应地转为 Map。这往往是 Map 转为数组 JSON 的逆操作。
1 2 3 4 5 6 | function jsonToMap(jsonStr) { return new Map(JSON.parse(jsonStr)); } jsonToMap( '[[true,7],[{"foo":3},["abc"]]]' ) // Map {true => 7, Object {foo: 3} => ['abc']} |
学习网站地址:http://caibaojian.com/es6/destructuring.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构