始终以来,JS 只能应用数组和对象来保留多个数据,不足像其余语言那样领有丰盛的汇合类型。因而,ES6 新增了两种汇合类型 set
和 map
,用于在不同的场景中发挥作用。因为文章篇幅的起因,明天先聊聊 set,map 将在下一篇文章再去说。
「set 汇合用于寄存不反复的数据」
0、如何创立 set 汇合
new Set();//创立一个没有任何内容的set汇合new Set(iterable);//创立一个具备初始内容的set汇合,内容来自于可迭代对象每一次迭代的后果
例:创立没有内容的 set 汇合
const result = new Set(); console.log(result);
执行后果:
例:创立一个可迭代对象的汇合
const result = new Set([1,3,3,4,5,5,6]); console.log(result);
执行后果:
在文章结尾咱们就提到set汇合用于寄存不反复的数据
,所以最初输入后果就是不反复的数组,这也是一种非常简单的数组去重的形式。当然 Set(数据)的参数不肯定是数组,只有是可迭代对象都能够,甚至能够是字符串
,如下:
const result = new Set('abbccdde'); console.log(result);
执行后果:
如果是字符串,它会先转换为String对象
,String对象其实是可迭代对象,从执行后果来看Set汇合不仅能够用于数组去重
,也能够用于字符串去重
。
1、如何对set汇合进行后续操作
「1、add(数据):增加一个数据到set汇合开端,如果数据已存在,则不进行任何操作」
例:应用add增加数据
const result = new Set(); result.add(1); result.add(2); result.add(3); result.add(1);//有效代码,Set外部会认为这条数据跟后面的数据反复 result.add(2);//有效代码,Set外部会认为这条数据跟后面的数据反复 console.log(result);
执行后果:
这外面有个细节大家要留神!
下:set外面它是怎么判断两个数据是否雷同呢? set应用Object.is
的形式判断两个数据是否雷同,而不是用===严格相等
,然而,针对+0和-0,set认为它们是相等的,什么意思呢?其实是这样:
Object.is(+0,-0);//返回false+0 === -0;//返回true
原本set是应用Object.is形式来判断数据是否相等,但set独自针对这块又把+0和-0看成相等的。代码测试:
const result = new Set(); result.add(1); result.add(2); result.add(3); result.add(1);//有效代码,Set外部会认为这条数据跟后面的数据反复 result.add(2);//有效代码,Set外部会认为这条数据跟后面的数据反复 result.add(+0); result.add(-0);//因而这段代码是有效的 console.log(result);
执行后果:
本不应该呈现这种状况的,之所以呈现这个问题,纯正是设计的问题,设计者预计是没方法开脱的,他不应该这样去设计,一个语言设计上它要对立。ES的设计不可能是一个人实现的,是很多人一起设计开发的,难免会造成不对立的状况。
还有一点就是如果判断的数据是对象是否相等,那么就要判断它的地址是否相等。
「2、has(数据):判断set中是否存在对应的数据」
因为set汇合中曾经应用add增加好数据,那么我间接应用has办法
执行后果:
「3、delete(数据):删除匹配的数据,返回是否删除胜利」
执行后果:
如果删除存在的数据就会返回true,如果是删除不存在的数据,则返回false
「4、clear():没有参数,清空整个set汇合」
执行后果:
2、如何与数组进行转换
例:数组转换成set汇合
const result = new Set(要转换的数组)
例:set汇合转换为数组
const arr = [...result];
接下来咱们看一个小例子:要求就是把一个数组去重之后失去一个新的数组。
例:数组去重失去新的数组
var arr = [1,1,33,44,21,23,56,34,56,56,77,77];const result =[...new Set(arr)];console.log(result);
执行后果:
以上就是非常简单地数组去重办法
顺便写下字符串去重
例:字符串去重
var str = 'asndjfnajsknfdqwpsfdnsifnasnfdijsf';const result =[...new Set(str)].join(" ");console.log(result);
执行后果:
3、如何遍历
方才咱们曾经说了,set自身是可迭代对象,因而能够用for of
循环进行遍历。
- 应用
forof
进行遍历
const result = new Set([1,1,33,44,21,23,56,34,56,56,77,77]); for (const item of result) { console.log(item);}
执行后果:
- 应用set中实例办法
forEach
const result = new Set([1,1,33,44,21,23,56,34,56,56,77,77]); result.forEach(item => { console.log(item);})
执行后果:
应用forEach遍历咱们要留神,在数组中进行遍历的时候,forEach是有三个参数的forEach(item,index,that),第一个参数是每一项的值,第二个参数是下标,第三个参数是数组自身。然而在set外面是有差异的,咱们加上三个参数试试:
const result = new Set([1,1,33,44,21,23,56,34,56,56,77,77]); result.forEach((item,index,that) => { console.log(item,index,that); })
执行后果:
咱们能够发现第一个参数和第三个参数没有问题,因为在数组中第一个参数也是每一项的值,第三个参数是数组自身,而第二个参数却不是下标,那为什么不是下标呢?
留神:
set汇合中不存在下标,因为下标是数组特有的货色,不要认为是汇合特有的货色,比方,对象也是汇合,外面能够存多个数据,对象就没有下标。因而在set汇合中是不可能获取下标的,那自然而然不可能用一般for循环去循环它的下标,如果说肯定要用下标的话,能够先把set汇合转换为数组再应用它的下标。因为set汇合中不存在下标,那么第二个参数就不是下标了。
但forEach又要放弃格局统一性,之所以要放弃格局对立是因为咱们有可能会写一些通用的回调函数既适宜数组调用,又适宜set汇合,为了保障通用性,因而set汇合中的forEach依然会保留第二个参数,只不过第二个参数跟第一个参数是一样的,都示意汇合中的每一项。
「set汇合中不存在下标,因而forEach中的回调的第二个参数和第一个参数是统一的,均示意set中的每一项。」
4、set汇合的利用
求两个数组的并集、交加、差集 (不能呈现反复项),失去的后果是一个新数组
例:求并集
const arr1 = [22,33,55,33,11,5,6];const arr2 = [22,55,77,88,88,99];//办法一:const result = [...new Set(arr1.concat(arr2))];console.log("并集",result);//办法二:const result = [...new Set([...arr1,...arr2])];console.log("并集:",result);
执行后果:
例:求交加
const arr1 = [22,33,55,33,11,5,6];const arr2 = [22,55,77,5,88,99];//办法一:const s1 = new Set(arr1);const s2 = new Set(arr2);const result = [...s1].filter(item => s2.has(item));console.log("交加:",result);//办法二const s = new Set(arr1);const result = [...s].filter(item => arr2.indexOf(item) >=0 )console.log("交加:",result);
执行后果:
例:求差集
const arr1 = [22,33,55,33,11,5,6];const arr2 = [22,55,77,5,88,99];//办法一const s1 = new Set(arr1);const s2 = new Set(arr2);const result = new Set([...s1,...s2].filter(item => !s2.has(item) || !s1.has(item)));console.log("差集:",result);//办法二const s1 = new Set(arr1);const s2 = new Set(arr2);const result = [...s1,...s2].filter(item =>arr1.indexOf(item) >=0 && arr2.indexOf(item) <0 || arr2.indexOf(item) >=0 && arr1.indexOf(item)<0)console.log("差集:",result);
执行后果:
5、手写set办法
咱们手写的set办法跟浏览器提供的set比照的话必定是不一样的,因为浏览器在实现ES规范的时候,它是能够调用底层资源的,比如说能够间接操作内存,它的效率要比咱们手写的set办法效率高些。手写源码能够拓展咱们的思维,仅此而已。
1、新建mySet.js文件
class MySet { //构造函数外面参数可传可不传,给参数一个默认值就能够了 constructor(iterable = []) { //验证传入的参数是否是可迭代对象,可迭代的对象类型肯定是个对象 if (typeof iterable[Symbol.iterator] !== 'function') { throw new TypeError(`${typeof iterator} ${iterator} is not iterable (cannot read property Symbol(Symbol.iterator))`) } this._datas = []; //因为不能操作底层内存,所以申明一个数组用于存放数据 //上面验证通过,迭代每一个可迭代的对象,把每一项放到 MySet外面去 for (const item of iterator) { //每迭代一次,把item加到 MySet外面去,问题转为封装add办法 this.add(item); } } //给 MySet增加数据 add(data) { //这里加数据的时候有个前提条件,就是反复的数据只放一次,问题转为封装has办法 if (!this.has(data)) { this._datas.push(data); } } //判断 MySet中是否存在对应的数据 has(data) { //这里判断是否有雷同的值,问题转为封装isEqual办法 for (const item of this._datas) { if (this.isEqual(data, item)) { return true; } } return false; } //删除 MySet中对应的数据 delete(data) { for (let i = 0; i < this._datas.length; i++) { const element = this._datas[i]; if (this.isEqual(element, data)) { //删除 this._datas.splice(i, 1); return true; } } return false; } //清空整个数组 clear() { this._datas.length = 0; } *[Symbol.iterator]() { for (const item of this._datas) { yield item; } } forEach(callback) { for (const item of this._datas) { callback(item, item, this); } } /** * 判断两个数据是否相等 * @param {*} data1 * @param {*} data2 */ isEqual(data1, data2) { //如果data1和data2都等于0,那么咱们认为它们相等 if (data1 === 0 && data2 === 0) { return true; } return Object.is(data1, data2); }}
代码测试:求差集
`<script src="js/mySet.js"></script>
<script > const arr1 = [22,33,55,33,11,5,6];
const arr2 = [22,55,77,5,88,99];
const s1 = new MySet(arr1);
const s2 = new MySet(arr2);
const result = new MySet([...s1,...s2].filter(item => !s2.has(item) || !s1.has(item)));
console.log("差集:",result); </script>`
执行后果:
代码测试:add、has、delete、clear
<script src="js/mySet.js"></script><script > const result = new MySet(); result.add(1); result.add(2); result.add(3); result.add(4); console.log(result);</script>
以上就是我的分享,心愿能帮到大家!欢送大佬一起探讨......