一、set 集合
Set:它类似于数组,但是成员的值都是唯一的,没有重复的值。set用于存放不重复的数据
1、创建Set 集合
new Set(); //创建一个没有任何内容的set集合
new Set(iterable); //创建一个具有初始内容的set集合,内容来自于可迭代对象每一次迭代的结果
const arr = [1,2,3,4,5,1,2]
const sets = new Set(arr)
console.log(sets)
2、Set 集合的增删改查
(1)add(data):添加一个数据到set集合末尾,如果数据已存在,则不进行任何操作
(2)has(data): 判断set中是否存在对应的数据
(3)delete(data):删除匹配的数据,返回是否删除成功
(4)clear():清空整个set集合
(4)size:获取set集合中的元素数量,只读属性,无法重新赋值
const arr = [1,2,3,4,5,2]
//const sets = new Set([1,2,3,4,5,2])
const sets = new Set(arr)
sets.add(7) //Set(6) {1, 2, 3, 4, 5, 7}
sets.delete(2) //Set(5) {1, 3, 4, 5, 7}
const res = sets.has(2)//false
sets.size //5
sets.clear() //Set(0){}
注意:Set 使用Object.is()的方式判断两个数据是否相同,但是,针对+0和-0,set认为是相等
3、与数组字符串进行相互转换
const s = new Set([x,x,x,x,x]);
// set本身也是一个可迭代对象,每次迭代的结果就是每一项的值
const arr = [...s];
数组去重:
let arr = [1,2,3,4,5,1,2]
arr = [...new Set(arr)]
console.log(arr)
字符串去重:
let str = "aslfhjiowvmlkpwifgefjmsa"
str = [...new Set(str)].join("")
console.log(str)
4、Set 遍历
(1)使用for-of循环
const sets = new Set([1,5,2,4,3,2])
for (const item of sets) {
console.log(item) //1
}
(2)使用set中的实例方法forEach
const sets = new Set([1,5,2,4,3,2])
sets.forEach((ele,index,s) => {
//set集合中没有下标,因此ele和index是一样的
console.log(ele,index,s) //1 1 Set(5) {1, 5, 2, 4, 3}
});
注意:set集合中不存在下标,因此forEach中的回调的第二个参数和第一个参数是一致的,均表示set中的每一项
求两个数组的并集,交集,差集
const arr1 = [1,4,7,9,6,0]
const arr2 = [4,5,6,1,3,2]
//并集
const result1 = [...new Set(arr1.concat(arr2))]
const result2 = [...new Set([...arr1,...arr2])]
console.log("并集",result1,result2)
//交集
let s1 = new Set(arr1)
let s2 = new Set(arr2)
const result3 = [...s1].filter(item=>{
return s2.has(item)
})
console.log("交集",result3)
//差集
const result4 = [...new Set([...arr1,...arr2])].filter(item=>result3.indexOf(item)<0)
console.log("差集",result4)
5、手写Set (仿照,并非真实底层实现)
//手写set
class MySet{
constructor(iterator = []){
//验证是否可迭代对象 Symbol.iterator知名符号
if(typeof iterator[Symbol.iterator] !== "function"){
throw new TypeError("你提供的不是可迭代的对象")
}
this._datas = []; //存放set数据
for (const item of iterator) {
this.add(item)
}
}
//set的添加方法
add(data){
if(!this.has(data))
this._datas.push(data)
}
//判断是否含有一个元素。
has(data){
for (const item of this._datas) {
if(this.isEqual(item,data)){
return true
}
}
return false
}
//判断两个元素是否相等,用Object.is()方法判断。特殊判断,+0和-0的情况
isEqual(data1,data2){
if(data1 === 0 && data2 === 0){
return true
}
return Object.is(data1,data2)
}
//删除元素
delete(data){
for(let i=0;i<this._datas.length;i++){
const ele = this._datas[i]
if(this.isEqual(ele,data)){ //找到元素
this._datas.splice(i,1) //删除元素
return true
}
}
return false
}
//清除元素的方法
clear(){
this._datas = []
}
*[Symbol.iterator](){
for(const item of this._datas){
yield item //迭代器中的关键字
}
}
//提供forEach方法迭代遍历
forEach(callback){
for (const item of this._datas) {
callback(item,item,this)
}
}
}
let s = new MySet([1,2,2,3,4,5])
console.log(s)
s.forEach((item,index,data)=>{
console.log(item,index,data)
})
二、WeakSet
WeakSet 集合与 Set 类似,也是不重复的值的集合
1、WeakSet 的成员只能是对象,而不能是其他类型的值。
const ws = new WeakSet();
ws.add(1)
// TypeError: Invalid value used in weak set
2、WeakSet 中的对象都是弱引用
垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
3、不能遍历(不是可迭代的对象)、没有size属性、没有forEach方法
三、Map集合
它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
键值对(key value pair)数据集合的特点:键不可重复.也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
map集合专门用于存储多个键值对数据。
1、创建Map
new Map(); //创建一个空的map
new Map(iterable); //创建一个具有初始内容的map,初始内容来自于可迭代对象每一次迭代的结果,但是,它要求每一次迭代的结果必须是一个长度为2的数组,数组第一项表示键,数组的第二项表示值
2、Map的增删改查
(1)size:只读属性,获取当前map中键的数量
(2)set(键, 值):设置一个键值对,键和值可以是任何类型
- 如果键不存在,则添加一项
- 如果键已存在,则修改它的值
- 比较键的方式和set相同
(3)get(键): 根据一个键得到对应的值
(4)has(键):判断某个键是否存在
(5)delete(键):删除指定的键
(6)clear():清空map
const map1 = new Map([["a",1],["b",2]])
map1.set({a:1},1) //0: {"a" => 1}
//1: {"b" => 2}
//2: {Object => 1}
//>key: {a: 1}
//>value: 1
console.log(map1.get("a")) //1
map1.delete("a")
console.log(map1.has("a")) //false
console.log(map1.size) //2
3、与数组互相转换
let arr = [[1,2],[3,4],[5,1]]
arr = [...new Map(arr)]
console.log(arr)
4、遍历
(1)for-of,每次迭代得到的是一个长度为2的数组
const map1 = new Map([["a",1],["b",2]])
for (const [key,value] of map1) {
console.log(key,value)
}
(2)forEach,通过回调函数遍历
const map1 = new Map([["a",1],["b",2]])
/*
参数1:每一项的值
参数2:每一项的键
参数3:map本身
*/
map1.forEach((key,value,m) => {
console.log(key,value,m)
});
5、手写Map
class MyMap{
constructor(iterator = []){
if(typeof iterator[Symbol.iterator] !== "function"){
throw new TypeError("Uncaught TypeError")
}
this._datas = []
for (const item of iterator) {
if(typeof item[Symbol.iterator] !== "function"){
throw new TypeError("Uncaught TypeErro")
}
const it = item[Symbol.iterator]()
const key = it.next().value
const value = it.next().value
this.set(key,value)
}
}
//设置key-value
set(key,value){
const obj = this._getObj(key)
if(obj){
obj.value = value
}else{
this._datas.push({key,value})
}
}
//获取value值
get(key){
const item = this._getObj(key)
if(item){
return item.key
}
return undefined
}
_getObj(key){
//根据key值,找到对想
for (const item of this._datas) {
if(this.isEqual(key,item.key)){
return item
}
}
return undefined
}
delete(key){
for(let i=0;i<this._datas.length;i++){
if(this.isEqual(key,this._datas[i].key)){
this._datas.splice(i,1)
return true
}
}
}
has(key){
return _getObj(key) !== undefined
}
isEqual(data1,data2){
if(data1 === 0 && data2 === 0){
return true
}
return Object.is(data1,data2)
}
}
const mymap = new MyMap([["a",1],["b",2]]);
mymap.set(1,2)
mymap.delete("a")
console.log(mymap)
四、WeakMap
1、WeakMap
只接受对象作为键名(null
除外),不接受其他类型的值作为键名。
const map = new WeakMap();
map.set(1, 2)// TypeError: 1 is not an object!
2、WeakMap
的键名所指向的对象,不计入垃圾回收机制。
3、WeakMap
size、forEach、clear 方法都不存在
const wm = new WeakMap();
wm.size // undefined
wm.forEach // undefined
wm.clear // undefined
- 它的键存储的地址不会影响垃圾回收
- 它的键只能是对象
- 不能遍历(不是可迭代的对象)、没有size属性、没有forEach方法
五、数组的扩展
1、静态方法
(1)Array.of(…args):使用指定的数组项创建一个新数组
const arr = Aarray.of(1,2,3,4,5)
//解决
const arr1 = new Array(1)//表示的是数组长度
(2)Array.from(arg):通过给定的类数组 或 可迭代对象 将它转为真正的数组。
const divs = document.querySelectorAll("div")
//Array.prototype.slice.call(divs,0)
const divArr = Array.from(divs)
2、实例方法
(1)find(callback):用于查找满足条件的第一个元素
const arr = [
{id:1,name:"llx"},
{id:2,name:"lkh"},
{id:3,name:"qqw"}
]
const result = arr.find(item=>item.id === 2)
console.log(result) //{id: 2, name: "lkh"}
(2)findIndex(callback):用于查找满足条件的第一个元素的下标
const arr = [1, 5, 10, 15]
const result = arr.findIndex((value, index, arr) => {
return value > 9;
})
console.log(result)// 2
(3)fill(data):用指定的数据填充满数组所有的内容
const arr = new Array(10)//表示的是数组长度
arr.fill(0)
console.log(arr) //[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
(4)copyWithin(target, start, end):在数组内部完成复制
const arr = [1,2,3,4,5,6]
arr.copyWithin(2) //[1, 2, 1, 2, 3, 4]
const arr = [1,2,3,4,5,6]
arr.copyWithin(2,1)// [1, 2, 2, 3, 4, 5]
const arr = [1,2,3,4,5,6]
arr.copyWithin(2,1,3) //[1, 2, 2, 3, 5, 6]
(5)includes(data):判断数组中是否包含某个值,使用Object.is匹配
const arr = [1,2,3,4]
arr.includes(2) //true