【ES6的新特性-Set集合和Map集合】

ES6新特性-Set集合、Map集合

  • 1、Set集合
    • 1.1创建方法
    • 1.2 操作方法
    • 1.3集合的遍历
    • 1.4 通过数组构造一个set集合
    • 1.5 通过Set实现A和B的并集
    • 1.6 通过Set实现A和B的交集
    • 1.7 WeakSet
  • 2、Map集合
    • 2.1 基本方法和属性
    • 2.2 遍历方法
    • 2.3 转为数组
    • 2.4 map中的元素进行过滤:使用过滤器filter
    • 2.5 forEach()
    • 2.6 WeakMap

1、Set集合

Set集合:是一种数据结构,结构类似于数组,且没有重复的值。主要用于数组去重,字符串去重。

1.1创建方法

(1)创建集合:new Set()

let set =new Set()

1.2 操作方法

方法 含义
add() 添加值,返回Set结构本身
delete() 删除值,返回一个boolean表示是否删除成功
has() 判断该值是否存在,并返回一个boolean
clear() 清除所有值,没有返回值

a、add():向集合中添加元素

let set =new Set()
set.add(1)
set.add(2)
set.add(2)//这个2添加不进去,集合里面不能有重复元素

set.add(3).add(12).add(15)
console.log(set)//会打印出集合信息
console.log(...set)//这个会将各个元素打印出来,不会打印出集合信息
console.log([...set])//会以数组方式显示集合

在这里插入图片描述

b、delete():从集合删除元素

set.delete(12)//返回true表示删除成功,false表示删除失败
console.log([...set])

在这里插入图片描述

c、has():判断集合中是否存在某个值


console.log(set.has(12))//判断集合是否含有12
console.log(set.has(15))

在这里插入图片描述

d、clear():清除集合中的所有元素

let set =new Set()
set.add(1)
set.add(2)
set.add(2)//这个2添加不进去,集合里面不能有重复元素

set.add(3).add(12).add(15)
console.log(set)//会打印出集合信息
console.log(...set)//这个会将各个元素打印出来,不会打印出集合信息
console.log([...set])//会以数组方式显示集合

set.delete(12)//返回true表示删除成功,false表示删除失败
console.log([...set])
console.log(set.has(12))//判断集合是否含有12
console.log(set.has(15))

set.clear()
console.log([...set])

【ES6的新特性-Set集合和Map集合】_第1张图片

1.3集合的遍历

集合的遍历:set集合中的key和value是相同的,所有key()和values()是一样的。

A、获取集合的keys和values进行遍历

let set = new Set()
set.add('西安').add('咸阳').add('宝鸡').add('铜川')
for(let i of set.keys()){//keys()函数的作用:获取set中的所有的键(key),返回的值也是集合
    console.log(i)
}
console.log('------------------------------')
for(let t of set.values()){//values()函数的作用:获取set中的所有的值(value),返回值也是集合
    console.log(t)
}
// 注意:set中的key和value是相同的,即keys()和values()的返回值是一样的

【ES6的新特性-Set集合和Map集合】_第2张图片

B、通过forEach循环

let set = new Set()
set.add('西安').add('咸阳').add('宝鸡').add('铜川')
set.forEach(function(key,val){//函数的两个参数的值是相同的
   // console.log(`${key}:${value}`)
    console.log(key)
})

【ES6的新特性-Set集合和Map集合】_第3张图片

1.4 通过数组构造一个set集合

let arr =[11,22,33,44,55]
let set =new Set(arr)
console.log(set)

在这里插入图片描述

1.5 通过Set实现A和B的并集

let arr =[11,22,33,44,55]
let list=[66,77,22,33]
let A =new Set(arr)
let B =new Set(list)
// 实现A和B的并集
let C=new Set([...A,...B])//将A和B的重复元素33剔除掉
console.log('A集合:',...A)
console.log('B集合:',...B)
console.log('A和B的并集:',...C)

在这里插入图片描述

1.6 通过Set实现A和B的交集

let arr =[11,22,33,44,55]
let list=[66,77,22,33]
let A =new Set(arr)
let B =new Set(list)
// 实现A和B的交集
let D = new Set([...A].filter(function(val){//通过过滤器找到A和B都出现的元素
   if(B.has(val)){
    return val
   }
}))
console.log('A和B的交集:',...D)

在这里插入图片描述

1.7 WeakSet

WeakSet只能是对象的集合,而不能是任何类型的任意值。

WeakSet集合中对象的引用为弱引用。如果没有其他的对WeakSet中对象的引用,那么这些对象会被当成垃圾回收掉。

这也意味着WeakSet中没有存储当前对象的列表。正因为这样,WeakSet 是不可枚举的。即WeakSet中对对象的引用不会被考虑进垃圾回收机制,即只要没有其他的对象引用该对象,则该对象就会被回收,而不管它在不在 WeakSet。

WeakSet 支持 add,has 和 delete 方法,但不支持 size 和 keys(),并且不可迭代,无法遍历

a、为weakSet添加对象,查看其返回值:

let jack = { name: "jack" }; //jack是一个对象
let weakSet = new WeakSet();
weakSet.add(jack); //为weakSet添加一个对象
console.log(weakSet.has(jack)); //判断weakSet是否含有jack,并输出返回值

得到结果为:true

b、为WeakSet添加除了对象之外的内容,查看其结果:

let jack = { name: "jack" }; //jack是一个对象
let weakSet = new WeakSet();
weakSet.add(1); //为weakSet添加除对象之外的值

程序会报错:TypeError: Invalid value used in weak set,因为WeakSet中只能存放对象。

WeakSet 的应用场景/好处:用于存储DOM节点,而不用担心这些节点从文档移除时会引发内存泄露。

2、Map集合

在ES5中没有Map:但是有object对象(采用hash结构:key=value),键(key)的数据类型只能是字符串。

2.1 基本方法和属性

A、属性:size表示集合中的元素个数

B、常用方法:

常用方法 说明
set() 添加数据
get() 获取数据
has() 判断key是否存在
delete() 删除key
clear() 清除所有的key

☀️举个例子

let map = new Map()//创建Map

map.set('id',1001) //set(key,value)
map.set('name','刘备')
map.set('age',25)

console.log(map.size)
let n = map.get('name')//get(key)
console.log(n)

console.log(map.has('age'))//has(key)

map.delete('id')
console.log(map.has('id'))//键不存在,对应的值也就不见了

map.clear()
console.log(map)

【ES6的新特性-Set集合和Map集合】_第4张图片

2.2 遍历方法

注意:Map的遍历顺序就是插入顺序

方法 含义
keys() 获取Map的所有key
values() 获取Map的所有值
entries() 获取Map所有成员
forEach() 遍历Map的所有成员
//创建一个map集合,传入一个二维数组
const map = new Map([
    ["F", "no"],
    ["T", "yes"]
])
console.log(map); 

输出结果为:Map(2) { ‘F’ => ‘no’, ‘T’ => ‘yes’ }

a、keys():返回map中的所有的键key

☀️举个例子

let map = new Map()//创建Map

map.set('id',1001) //set(key,value)
map.set('name','刘备')
map.set('age',25)
map.set('address','西安')
for(let key of map.keys()){
    // console.log(key)//这个只能打印出来键不能打印出来值
    console.log(`${key}:${map.get(key)}`)//将键值对打印出来
}

【ES6的新特性-Set集合和Map集合】_第5张图片

b、values():返回map中的所有值value

☀️举个例子

let map = new Map()//创建Map

map.set('id',1001) //set(key,value)
map.set('name','刘备')
map.set('age',25)
map.set('address','西安')
for(let val of map.values()){
    console.log(val)//这个只能打印出来值不能打印出来键
   
}

在这里插入图片描述

c、entries():返回map所有的map成员

☀️举个例子

let map = new Map()//创建Map

map.set('id',1001) //set(key,value)
map.set('name','刘备')
map.set('age',25)
map.set('address','西安')
for(let kv of map.entries()){
    console.log(kv)
   
}

【ES6的新特性-Set集合和Map集合】_第6张图片

d、forEach:对map的每个元素执行一次提供的函数

let map = new Map()//创建Map

map.set('id',1001) //set(key,value)
map.set('name','刘备')
map.set('age',25)
map.set('address','西安')
map.forEach(function(key,val){
    console.log(`${key}:${val}`)
})

在这里插入图片描述

2.3 转为数组

Map结构转为数组结构,比较快速的方法是使用扩展运算符(…)。

//创建一个map集合
const map = new Map([
    [1, "one"],
    [2, "two"],
    [3, "three"]
])
//将map的键转化为一个数组
console.log(...map.keys()); //1 2 3
//将map的值转化成一个数组
console.log(...map.values()); //one two three
//将map对象转化成一个数组
console.log(...map.entries()); //[ 1, 'one' ] [ 2, 'two' ] [ 3, 'three' ]
//将map转化成一个数组
console.log(...map); //[ 1, 'one' ] [ 2, 'two' ] [ 3, 'three' ]

let map = new Map()//创建Map
map.set('id',1001) //set(key,value)
map.set('name','刘备')
map.set('age',25)
map.set('address','西安')
// 将key转化为数组
let k = [...map.keys()]
console.log(k)    //输出:[ 'id', 'name', 'age', 'address' ]
// 将value转化为数组
let v=[...map.values()]
console.log(v)    //输出:[ 1001, '刘备', 25, '西安' ]
// 将key-value转换为数组
let obj = [...map.entries()]
console.log(obj)  
//输出:二维数组4行2列:
// [ 'id', 1001 ],
// [ 'name', '刘备' ],
// [ 'age', 25 ],
// [ 'address', '西安' ]

【ES6的新特性-Set集合和Map集合】_第7张图片

2.4 map中的元素进行过滤:使用过滤器filter

let map = new Map()
map.set('101',15)
map.set('102',5)
map.set('103',150)
map.set('104',28)
map.set('105',19)
map.set('106',30)
console.log(map)

// 将map中value是偶数的键值对(key-value)过滤出来,存入一个新的map中
let map1 = new Map([...map].filter(function([key,val]){
    if(val%2==0){
        return [key,val]
    }
}))
console.log(map1)

【ES6的新特性-Set集合和Map集合】_第8张图片

2.5 forEach()

const map = new Map([[1, 'one'], [2, 'two'], [3, 'three']]);
map.forEach((value, key, map) => {
    console.log(value, key, map);
})

输出结果为:
one 1 Map(3) { 1 => ‘one’, 2 => ‘two’, 3 => ‘three’ }
two 2 Map(3) { 1 => ‘one’, 2 => ‘two’, 3 => ‘three’ }
three 3 Map(3) { 1 => ‘one’, 2 => ‘two’, 3 => ‘three’ }

2.6 WeakMap

WeakMap是弱引用Map集合,也用于存储对象的弱引用。WeakMap集合中的键名必须是一个对象,如果使用非对象键名会报错。

集合中保存的是这些对象的弱引用,如果在弱引用之外不存在其他的强引用,引擎的垃圾回收机制会自动回收这个对象,同时也会移除WeakMap集合中的键值对。但是只有集合的键名遵从这个规则,键名对应的值如果是一个对象,则保存的是对象的强引用,不会触发垃圾回收机制。

1、使用WeakMap集合
ES6中的WeakMap类型是一种存储着许多键值对的无序列表,列表的键名必须是非null类型的对象,键名对应的值则可以是任意类型。

WeakMap的接口与Map非常相似,通过set()方法添加数据,通过get()方法获取数据。

let map = new WeakMap();
const o1 = {}; //o1是一个空对象
const o2 = function () { }; //o2是一个空函数
map.set(o1, o2); //给map添加数据,键和值可以是任意对象,甚至是另一个WeakMap对象
map.set(o2, "张三"); //为map添加数据
console.log(map.get(o1)); //[Function: o2]
console.log(map.get(o2)); //张三

在这里插入图片描述

WeakMap集合不支持size属性,从而无法验证集合是否为空。

2、WeakMap集合支持的方法

方法 含义
has() 检测给定的键在集合中是否存在
delete() 移除指定的键值对

a、has()使用示例:

let map = new WeakMap();
const o1 = {}; //o1是一个空对象
const o2 = function () { }; //o2是一个空函数
map.set(o1, o2); //给map添加数据,键和值可以是任意对象,甚至是另一个WeakMap对象
map.set(o2, "张三"); //为map添加数据
console.log(map.has(o1)); //判断map中是否含有o1,true
console.log(map.has(o3)); //判断map中是否含有o3,程序报错,ReferenceError: o3 is not defined

b、delete()使用示例:

let map = new WeakMap();
const o1 = {}; //o1是一个空对象
const o2 = function () { }; //o2是一个空函数
map.set(o1, o2); //给map添加数据,键和值可以是任意对象,甚至是另一个WeakMap对象
map.set(o2, "张三"); //为map添加数据
console.log(map.delete(o1)); //删除map中的o1,删除成功返回true
console.log(map.has(o1)); //判断map中是否含有o1

输出结果为:
true
false

3、WeakMap集合的用途

a、储存DOM元素

    <button id="btn">点击</button>
    <script>
        //获取button元素
        let myElement = document.getElementById("btn");
        let myWeakmap = new WeakMap();
        //为myWeakmap添加数据
        myWeakmap.set(myElement, { timesClicked: 0 });
        //为按钮添加click事件
        myElement.addEventListener("click", function () {
            //获取myWeakmap键为myElement的值
            let logoData = myWeakmap.get(myElement);
            //点击一次加一次1
            logoData.timesClicked++;
            //输出点击的次数
            console.log(logoData.timesClicked);
        })
    </script>

【ES6的新特性-Set集合和Map集合】_第9张图片
代码中,myElement是一个DOM节点,每当发生click事件,就更新一下状态。我们将这个状态作为键值放在WeakMap里,对应的键名就是myElement。一旦这个DOM节点删除,该状态就会自动消失,不存在内存泄漏风险

b、注册监听事件的listener对象,就很合适用WeakMap实现。

    <button class="element1">按钮1</button>
    <button class="element2">按钮2</button>
    <script>
        //获取元素
        let element1 = document.querySelector(".element1");
        let element2 = document.querySelector(".element2");
        const listener = new WeakMap();
        //为listener添加两个数据
        listener.set(element1, "handler1");
        listener.set(element2, "handler2");
        //为element1添加click事件
        element1.addEventListener("click", function () {
            console.log(listener.get(element1));
        })
        //为element2添加click事件
        element2.addEventListener("click", function () {
            console.log(listener.get(element2));
        })
    </script>

【ES6的新特性-Set集合和Map集合】_第10张图片
监听函数放在WeakMap里面。一旦 DOM 对象消失,跟它绑定的监听函数也会自动消失。

c、 部署私有属性

我们创建对象的时候,通常写一个构造函数

function Person(name) {
    this._name = name;
}
Person.prototype.getName = function () {
    return this._name;
}

但这时,创建一个Person 对象的时候,我们可以直接访问name属性

const person = new Person("张三");
console.log(person._name); //张三

我们不想让用户直接访问name属性, 直接使用下面的方法将name包装成私有属性。

let Person = (function () {
    let privateData = new WeakMap();
    function Person(name) { //定义一个函数,参数为name
        privateData.set(this, { name: name }); //为privateData设置数据
    }
    Person.prototype.getName = function () { //设置getName函数
        return privateData.get(this).name; //获得privateData中name键的值的name
    }
    return Person;
}()); //()()该函数设置之后就调用
const person = new Person("张三");
console.log(person.getName());

你可能感兴趣的:(javascript,es6,前端,javascript)