ES6学习笔记篇二之Set/Map集合和数组的扩展

一、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

扫描二维码关注公众号,回复: 9778953 查看本文章
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、WeakMapsize、forEach、clear 方法都不存在

const wm = new WeakMap();
wm.size // undefined
wm.forEach // undefined
wm.clear // undefined
  1. 它的键存储的地址不会影响垃圾回收
  2. 它的键只能是对象
  3. 不能遍历(不是可迭代的对象)、没有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
发布了21 篇原创文章 · 获赞 82 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Newbie___/article/details/104450142
今日推荐