JavaScript中Set与WeakSet类型

简介: JavaScript中Set与WeakSet类型

js中Set与WeakSet类型

Set(集合)

Set的创建

用于存储任何类型的唯一值,无论是基本类型还是对象引用。

  • 只能保存值没有键名
  • 严格类型检测如字符串数字不等于数值型数字
  • 值是唯一的
  • 遍历顺序是添加的顺序,方便保存回调函数

new Set()可以传入数组,返回一个类似于数组的对象。对象中的元素的值都是唯一的(相同值会被过滤)

let arr = new Set([1,2,3,1,1,2,3,4]);
console.log(arr);//Set(4) { 1, 2, 3, 4 }
arr.add(5);
arr.add(5);
console.log(arr);//Set(6) { 1, 2, 3, 4, 5, '5' }
console.log(typeof arr);//object

Set的基本 方法/属性

let set = new Set(['xiaoming','xiaohong','xiaobai','xiaohei']);

//获取元素数量
console.log(set.size);//4

//删除指定元素,有指定元素返回true,没有则返回false
console.log(set.delete('xiaoming'));//true
console.log(set.delete('xiaoxiao'));//false
console.log(set.size);//3

//查询是否有该元素,返回布尔值
console.log(set.has('xiaohei'));//true

//清除所有元素
set.clear();
console.log(set.size);//0

Set与Array的类型转换

有时候我们需要Set与Array类型相互转换,来借助相互的类型的方法或者特性。从而实现需求。

let set = new Set([1,2,3,4,5,6,7,8,9]);
//Set借助Array的filter来实现过滤大于5的数字
arr = [...set].filter( item => item <= 5);
console.log(set);//Set(9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
set = new Set(arr)
console.log(arr);//[ 1, 2, 3, 4, 5 ]
console.log(set);//Set(5) { 1, 2, 3, 4, 5 }

//Array借助Set的唯一值的特性来过滤相同值的元素
let arr1 = [1,2,3,3,2,1,4];
let set1 = new Set(arr1);
console.log(set1);//Set(4) { 1, 2, 3, 4 }
arr1 = Array.from(set1);
console.log(arr1);//[ 1, 2, 3, 4 ]

Set的遍历

Set的遍历与数组类似.

Set使用 keys()/values()/entries() 都可以返回迭代对象,因为set类型只有值所以 keys与values 方法结果一致。

let set = new Set(['xioaming','xiaohong']);
console.log(set.keys());//SetIterator {'xioaming', 'xiaohong'}
console.log(set.values());//SetIterator {'xioaming', 'xiaohong'}
console.log(set.entries());//SetIterator {'xioaming' => 'xioaming', 'xiaohong' => 'xiaohong'}

使用forEach和for/of遍历

let set = new Set([1,2,3,4,5]);
set.forEach((value,key) => console.log(value,key));//value与key相等

for (const value of set) {
  console.log(value);
}

Set的一些实际运用

可以用来收集用户在搜索框内提交的关键词,然后可以用里面的一些作为热门关键词

<body>
  <input type="text">
  <ul></ul>
  <script>
    let obj = {
        words: new Set(),
        keyword(word) {
            this.words.add(word);
        },
        show() {
            let ul = document.querySelector('ul');
            ul.innerHTML = '';
            this.words.forEach((item) => {
                ul.innerHTML += ('<li>' + item + '</li>');
            })
        }
    }
  
    document.querySelector('input').addEventListener('blur', function () {
        obj.keyword(this.value);
        obj.show();
    });
  </script>
</body>

Set处理并集 交集 差集

在实际开发中,可能会需要将两个用户的共同爱好或者不同爱好提取出来。这时候我们可以用Set来进行处理。

let a = new Set([1,2,3,4,5]);
let b = new Set([4,5,1,9]);

//并集
console.log(new Set([...a,...b]));//Set(6) { 1, 2, 3, 4, 5, 9 }
//交集
console.log(
  Array.from(a).filter( value => b.has(value) )//[ 1, 4, 5 ]
);
//差集
console.log(
  Array.from(a).filter( value => !b.has(value) )//[ 2, 3 ]
);

WeakSet(弱集)

WeakSet的创建

WeakSet结构同样不会存储重复的值,它的成员必须只能是对象类型的值。

  • 垃圾回收不考虑WeakSet,即被WeakSet引用时引用计数器不加一,所以对象不被引用时不管WeakSet是否在使用都将删除
  • 因为WeakSet 是弱引用,由于其他地方操作成员可能会不存在,所以不可以进行forEach( )遍历等操作
  • 也是因为弱引用,WeakSet 结构没有keys( ),values( ),entries( )等方法和size属性
  • 因为是弱引用所以当外部引用删除时,希望自动删除数据时使用 WeakMap

通过new WeakSet()进行声明,如果有初值的时候,注意必须是引用类型(Object 或者继承自 Object 的类型),否则会报错。

// console.log(new WeakSet('asdf'));//WeakSret is not defined
// console.log(new WeakSret(['qwer','asdf']));
//WeakSret is not defined 这里虽然看上去是传入的是一个数组,但是传入构造函数的是两个字符串
console.log(new WeakSet());

WeakSet的 基本方法/属性

let obj1 = {age:18};
let weak = new WeakSet([obj1]);//传入一个含有obj对象的元素
let obj2 = {age:16};
//添加
weak.add(obj2);
//查询
console.log(weak.has(obj2));//true
console.log(weak.has(obj1));//true
//删除
weak.delete(obj1);
console.log(weak);

js垃圾回收与WeakSet

在js中,如果一个内存空间没有被引用。则会被js垃圾回收机制删除内存空间。

let obj = {
  name: 'xiaoming'
}
console.log(obj);//{ name: 'xiaoming' }
obj = null;//让该对象不指向任何内存空间(当前obj未设置值)
console.log(obj);//null 这时候 {name: 'xiaoming'}没有被引用,js就会对该内存空间进行垃圾回收
let obj1 = {age:18};
let arr = ['qwer'];
//如果直接向里面传值,而不是值的引用,打印WeakSet时无法读到值。
//因为开辟的内存空间没有被引用,被js的垃圾回收机制清理了
let weak = new WeakSet([obj1,arr,['asdf']]);
let obj2 = {age:16};
obj1 = {};//obj指向了新的内存空间
obj1 = {age:18};//这里的{age:18}与原来的不是同一个内存空间
weak.add(obj2);
console.log(weak.has(obj2));//true
console.log(weak.has(obj1));//false
// weak.delete(obj1);
console.log(weak);
setTimeout(() => {
console.log(weak);
}, 1000);

在打印的WeakSet中可以看到:WeakSet认为里面有四个值,但实际上只有两个值。而出现这种情况的原因是:WeakSet里面的值因为没有被引用(垃圾回收不考虑WeakSet),所以实际上已经被进行垃圾回收了。可以看到下面延迟打印的WeakSet里面就只有被引用的值。

实践应用场景为储存DOM元素

相关文章
|
21天前
|
JavaScript
常见函数的4种类型(js的问题)
常见函数的4种类型(js的问题)
11 0
|
1月前
|
JSON JavaScript 前端开发
解决js中Long类型数据在请求与响应过程精度丢失问题(springboot项目中)
解决js中Long类型数据在请求与响应过程精度丢失问题(springboot项目中)
41 0
|
23天前
|
JavaScript 前端开发
JavaScript 中如何检测一个变量是一个 String 类型?
JavaScript 中如何检测一个变量是一个 String 类型?
21 2
|
3月前
|
JavaScript 前端开发 定位技术
JavaScript 中如何代理 Set(集合) 和 Map(映射)
JavaScript 中如何代理 Set(集合) 和 Map(映射)
50 0
|
3月前
|
JSON JavaScript 前端开发
抓住异常,解救你的代码世界:你应该了解的 JavaScript 异常类型
抓住异常,解救你的代码世界:你应该了解的 JavaScript 异常类型
|
1天前
|
存储 JavaScript 索引
js开发:请解释什么是ES6的Map和Set,以及它们与普通对象和数组的区别。
ES6引入了Map和Set数据结构。Map的键可以是任意类型且有序,与对象的字符串或符号键不同;Set存储唯一值,无重复。两者皆可迭代,支持for...of循环。Map有get、set、has、delete等方法,Set有add、delete、has方法。示例展示了Map和Set的基本操作。
11 3
|
9天前
|
索引 Python
python 格式化、set类型和class类基础知识练习(上)
python 格式化、set类型和class类基础知识练习
32 0
|
21天前
|
JavaScript 前端开发
JavaScript数组的功能内置类型
数组是JavaScript的内置类型,JavaScript数组的功能特别强大。下面简单介绍一下JavaScript数组。
|
23天前
|
存储 JavaScript 前端开发
JavaScript 中松散类型的理解
JavaScript 中松散类型的理解
26 3
|
1月前
|
存储 C++ 容器
在C++的set的作用类型
在C++的set的作用类型
9 0