es6常用的数组方法(ES6中Set与WeakSet集合的深入讲解)
es6常用的数组方法
ES6中Set与WeakSet集合的深入讲解目录
- Set是值永不重复的特殊集合
- Set集合基础API
- 关于唯一值的判断
- Set集合遍历的3种方式
- Set集合案例实践
- Set集合与Array数组之间的转换
- 单个数组去重
- 多个数组合并去重
- 获取交集(重复的元素)
- 判断是否有交集(重复的元素)
- 获取差集:只返回重复
- WeakSet“弱”在哪里?
- 弱功能
- 弱引用
- 总结
每天都用数组,有没有过一个Moment,担心插入了重复的值?使用Set集合吧!Set拥有特殊的数据结构,保证插入的值永远不会重复。
Set集合基础API通过Set.prototype.constructor 构造函数创建Set实例
/* * 仅实例化:调用构造函数,不传参数 */ let empty_set = new Set() /* * 实例化同时初始化:传入任意iterate对象,将其转换成Set集合 */ let transfer_set4arr = new Set([1, 2, 3]) // 返回Set(3) {1, 2, 3} let transfer_set4string = new Set("huilin") // 返回Set(5) {"h", "u", "i", "l", "n"} let transfer_set4set = new Set(new Set([5, 6])) // 返回Set(2) { 5, 6 }
访问 Set.prototype.size属性,返回集合中元素的个数
console.log(empty_set.size) // 0 console.log(transfer_set4arr.size) // 3
调用 Set.prototype.has(value) 方法,判断元素是否存在
// 相比起Array.includes(),Set.has()性能更高,因为专门对成员测试进行了优化 console.log(empty_set.has(1)) // false console.log(transfer_set4arr.has('h')) // true
关于唯一值的判断
- Set集合为确保值的唯一性,使用Object.is(value1,value2)进行判断,而不是通过===(恒等符号)符号来判断的,因为恒等判断会将两边的变量进行强制类型转换。
- 比如,两个变量的值均为NaN,或者0和-0,用JS判断是不相等的,但Object.is()认为是同一个只,因此不能存入Set集合中。
想了解更多关于Object.is(),请跳转查看:developer.mozilla.org/zh-CN/docs/…
let n1 = NaN let n2 = NaN console.log(n1 === n2) // 恒等符号判断两者不一致,输出false console.log(Object.is(n1,n2)) // 但Object.is()判断两者是相同的,输出false // Set集合不允许将两个NaN放入集合 let set = new Set() set.add(n1).add(n2) console.log(set.size) // size: 1
而面对复杂数据类型时,主要通过对象的引用进行判断。引用不一致,即便数据结构一致,也认为只不相同,因此能存入Set集合。
let same_value_set = new Set(); // 先存入一个对象 same_value_set.add({num: 0}); // 再存入一个结构一致的新对象 let obj = {num: 0}; same_value_set.add(obj); // 都能存入成功 console.log(same_value_set.size); // 2
调用Set.prototype.add(value) 方法,向集合追加数据
// add()方法可以追加任意类型的数据,不论是原始值或者是对象引用 let set1 = new Set() // 由于add()方法始终返回当前实例的引用,所以进行链式调用 set1.add(1).add(2).add(3) console.log(set1) // Set(3) {1, 2, 3} // 注意:当add()传入数组时,Set会将数组实例插入集合,而不是数组内的元素 set1.add([4, 5]) console.log(set1) // Set(4) {1, 2, 3, [4, 5]}
调用Set.prototype.delete(value) 方法,移除集合中的元素
// delete()方法返回移除操作是否成功,与.has()方法一样 let success = set1.delete(1) console.log(success) // true
调用Set.prototype.clear() 方法,清空集合
let num_set = new Set([1, 6, 3]) console.log(num_set) // Set(3) { 1, 6, 3 } set1.clear() console.log(num_set) // Set(0) {}
Set集合遍历的3种方式
由于集合没有下标/索引,通常被认为是“无序集合”。但JavaScript会记住元素插入的顺序,所以遍历的时候也按顺序对元素进行迭代。
直接遍历Set集合
let set = new Set([1, 2, 3, 4, 5]) for(let item of set){ console.log(item) } // 依次输出:1 2 3 4 5
创建迭代器进行遍历
/* * 创建迭代器的有三种方式 * Set.prototype.entries() * Set.prototype.keys() * Set.prototype.values() */ // Set集合只有value而没有key,但为了使得和遍历Map对象相似,Set.entries()创建新的Iterator对象时,每一项的键和值都相等,即[value,value] for(let [key,value] of set.entries()){ console.log(value) } // 依次输出:1 2 3 4 5 // Set.keys()创建新的Iterator对象,返回每一项值 for(let key of set.keys()){ console.log(key) } // 依次输出:1 2 3 4 5 // Set.values()和Set.keys()一致,返回每一项的值 for(let value of set.values()){ console.log(value) } // 依次输出:1 2 3 4 5
调用Set.prototype.forEach(callbackFn)方法遍历
// forEach(callbackFn) 按照插入顺序调用callbackFn,取出每项值 set.forEach(item => { console.log(item) }) // 依次输出:1 2 3 4 5
Set集合与Array数组之间的转换
/* * Set转Array */ let set1 = new Set([1, 2, 3]) // Array.from()方法 let arr1 = Array.from(set1) // 扩展运算符 let arr2 = [...set1] /* * Array转Set */ // 利用Set构造函数 let set = new Set(array)
单个数组去重
let set = new Set([1, 2, 4, 4, 2, 5]) console.log(set) // Set(4) { 1, 2, 4, 5 }
多个数组合并去重
let arr1 = [1, 2, 4] let arr2 = [1, 5, 6] // 利用Set集合的特性,集合内的元素都是唯一的 let result = new Set([...set1, ...set2]) console.log(result) // Set(5) { 1, 2, 4, 5, 6 }
获取交集(重复的元素)
let set1 = new Set([1, 2, 4]) let set2 = new Set([1, 5, 6]) // 返回set1和set2都存在的元素 let result = new Set([...set1].filter(x => set2.has(x))) console.log(result) // Set(1) { 1 }
判断是否有交集(重复的元素)
let set1 = new Set([1, 2, 4]) let set2 = new Set([1, 5, 6]) function isMixed(set, subset) { for (let elem of subset) { if (set.has(elem)) { return true; } } return false; } console.log(isMixed(set1, set2)) // true
获取差集:只返回重复
let set1 = new Set([1, 2, 4]) let set2 = new Set([1, 5, 6]) function difference(setA, setB) { let result = new Set() for (let elem of setB) { if(setA.has(elem)){ result.add(elem) } } return result; } console.log(difference(set1, set2))
除了Set集合外,ES6还提供了WeakSet和WeakMap。既然集合的名字都叫“Weak(弱)的集合”了,究竟它“弱”在哪里呢?
弱功能
WeakSet不允许插入原始值,仅支持对象的引用;
let val1 = {id: 1}, val2 = {id: 2} let ws = new WeakSet() // 和Set集合一样,WeakSet的值也不重复,同时add()也返回集合实例,所以可以链式操作 ws.add(val1).add(val1).add(val2) // 不允许插入基础数据类型 ws.add(3) // 报错:TypeError:Invalid value used in WeakSet // 但可以先包装成对象后再插入 let val3 = new Number(3) ws.add(val3) console.log(ws.has(val3)) // 输出:true
- WeakSet仅实现了add()、has()、delete()三个操作方法;
- WeakSet不允许遍历,也没有size或者length属性;
弱引用
要说弱引用,先看看什么是强引用:
// 声明一个对象 let handsome = { name: 'huilin', age: 30 } // 放入数组 let arr = [1, handsome, 2] console.log('release before arr length', arr.length) // 3 // 放入Map let user = { oid: 10001, classify: 'Chinese', staffReference: handsome } console.log('release before map length', Object.keys(user).length) // 3 console.log('----') // 突然把对象置为null handsome = null // 强引用的容器中,对象仍然存在没有被回收 console.log('release after arr length', arr.length) // 3 console.log(arr[1]) // { name: 'huilin', age: 30 } console.log('release after map length', Object.keys(user).length) // 3 console.log(user.staffReference) // { name: 'huilin', age: 30 }
从测试代码看出,除非容器销毁,否则引用的对象一直没有被回收。而所谓弱引用,就是希望容器是根据元素自动伸缩的,一旦对象为null,容器中的引用也跟着回收。
let obj1 = { name: 'huilin', age: 30 } let obj2 = { name: 'cc', age: 29 } let ws1 = new WeakSet() ws1.add(obj1).add(obj2) console.log(ws1.has(obj1)) // true // 不管是从容器操作元素 ws1.delete(obj1) console.log(ws1.has(obj1)) // false // 或者是对象自己置为null,都会自动回收 obj2 = null console.log(ws1.has(obj2)) // false
Reference
- zh.javascript.info/map-set
- es6.ruanyifeng.com/#docs/set-m…
到此这篇关于ES6中Set与WeakSet集合的文章就介绍到这了,更多相关ES6 Set与WeakSet集合内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
- mysqlupdate语句用法(MySQL update set 和 and的区别)
- react的setstate第二个参数(示例详解react中useState的用法)
- vue设置属性没响应(Vue.$set 失效的坑 问题发现及解决方案)
- mysql的复制原理(浅析MySQL的WriteSet并行复制)
- dataset详解(DATASET 与 DATAREADER对象有什么区别)
- python dict 操作(Python中dict和set的用法讲解)
- phpob函数使用方法(php中isset与empty函数的困惑与用法分析)
- phpsetcookie参数说明(PHP的cookie与session原理及用法详解)
- dataset用法
- SQL Server中GROUPING SETS
- mysqlinnodb数据存储格式(MySQL InnoDB ReplicaSet副本集简单介绍)
- setTimeout和setIntelval的用法和区别
- androidjpg图像处理(详解如何使用image-set适配移动端高清屏图片)
- html5中table属性(Html5之自定义属性data-,dataset)
- ASP.NET中XML与DataSet的相互转换
- Jquery中的offset()和position()的区别
- 英语难学吗(初中英语难学吗)
- 如何追女孩子(如何追女孩子的技巧和方法)
- 是不是快乐全被你拿走了(而是你得到的)
- 世界上只有妈妈好(世界上只有妈妈好的歌词)
- 为什么现在社会越来越卷了(现在社会为什么发展那么快呢)
- 直播带货能赚到很多钱吗(直播带货能赚到很多钱吗现在)
热门推荐
- mysql重启启动失败(MySQL8.0无法启动3534的解决方法)
- sql语句去除重复记录(使用SQL语句去掉重复的记录两种方法)
- C#冒泡排序
- docker中国加速镜像怎么设置(Docker 安装及配置镜像加速的实现)
- 宝塔linux面板php7.0安装不上(宝塔面板php.ini文件在哪里找)
- SET NOCOUNT ON 作用
- linux设置lib目录(Linux如何使用libudev获取USB设备VID及PID)
- 宝塔面板安装ssl证书网站打不开(宝塔面板如何配置SSL证书?)
- dede头部文件在哪(dede专题节点文章按id,点击等类型排序)
- laravel后台框架(laravel-admin的多级联动方法)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9