ES6指的是ECMAScript 6,也被称为ES2015。它是JavaScript的一种版本,是ECMAScript标准的第六个版本,于2015年发布。ECMAScript是JavaScript的规范,定义了语言的核心特性和行为。ES6引入了许多新的语法特性和功能,以使JavaScript代码更加现代化、清晰和强大。 在此专栏中,我们会持续更新有关于ES6的新特性,感兴趣的小伙伴们可以订阅一下~
前言
今天我们来聊聊ES6新特性中的weakset
,WeakSet
(弱引用集合)是 JavaScript 中的一种数据结构,用于存储对象的弱引用集合。与常规集合不同,WeakSet
仅允许对象作为键,并且不允许使用原始值。WeakSet
中的对象引用是弱引用,这意味着如果没有其他强引用指向某个对象,该对象可能会被垃圾回收器回收,即使它存在于 WeakSet
中。
Weakset
WeakSet
的语法相对简单,它使用 new WeakSet()
构造函数创建一个新的 WeakSet
实例。以下是详细的语法说明:
创建 WeakSet
实例
使用 new WeakSet()
构造函数创建一个新的 WeakSet
实例:
js
let weakSet = new WeakSet();
操作方法
WeakSet
提供了几个操作方法,用于向集合中添加、检查或删除元素。
-
add(value): 向
WeakSet
中添加一个对象。jslet obj1 = { key: 'value' }; let weakSet = new WeakSet(); weakSet.add(obj1);
-
delete(value): 从
WeakSet
中删除指定对象。jslet obj1 = { key: 'value' }; let weakSet = new WeakSet(); weakSet.add(obj1); weakSet.delete(obj1);
-
has(value): 检查
WeakSet
中是否包含指定对象,返回一个布尔值。jslet obj1 = { key: 'value' }; let weakSet = new WeakSet(); weakSet.add(obj1); console.log(weakSet.has(obj1)); // true
注意事项
-
只能包含对象:
WeakSet
只能包含对象作为其元素,而不能包含原始值。jslet weakSet = new WeakSet(); // 以下行为是无效的 weakSet.add('Hello'); // TypeError: Invalid value used in weak set
-
不可迭代:
WeakSet
不具备迭代的能力,因此无法使用类似forEach
的方法直接遍历其元素。
Weakset的弱引用特性
WeakSet
使用弱引用的特性,这与传统的引用不同。在 JavaScript 中,引用通常是强引用,即如果一个对象被引用,它将不会被垃圾回收。而使用弱引用的数据结构,例如 WeakSet
,在对象只有弱引用时,不会阻止对象被垃圾回收。
弱引用:
弱引用是指一个对象的引用,不会阻止垃圾回收器回收该对象。如果一个对象只有弱引用,那么当没有其他强引用指向它时,垃圾回收器可能会将其回收。在 WeakSet
中,它存储的是对象的弱引用,这意味着 WeakSet
不会阻止垃圾回收器回收它所包含的对象。
WeakSet
的垃圾回收机制:
- 垃圾回收: 如果在
WeakSet
中唯一引用某个对象的是弱引用,且没有其他强引用指向该对象,垃圾回收器可能会在适当的时机回收该对象。这是因为在 JavaScript 中,垃圾回收器的目标是回收不再被引用的对象。
示例:
js
let weakSet = new WeakSet();
let obj = { key: 'value' };
weakSet.add(obj);
console.log(weakSet.has(obj)); // true
obj = null; // 移除对 obj 的强引用
// 此时,垃圾回收器可能会回收 obj,并从 WeakSet 中移除相应的弱引用
console.log(weakSet.has(obj)); // false
在这个例子中,当 obj
被设置为 null
时,强引用被移除,这可能导致 obj
变得不再可达。因为 WeakSet
中的引用是弱引用,垃圾回收器可能会回收 obj
,并从 WeakSet
中移除相应的弱引用。这突显了 WeakSet
的一个主要特性,即它不会阻止对象被垃圾回收。
那我们什么时候可以使用Weakset去达成我们想要的效果呢?
当我们点击一次按钮后,按钮会被禁用或者消失:
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="wrap">
<button id="btn">确认</button>
</div>
<script>
let wrap = document.getElementById('wrap');
let btn = document.getElementById('btn');
// 给btn打上标签
const disabledElements = new WeakSet()
disabledElements.add(btn)
btn.addEventListener('click', () => {
wrap.removeChild(btn)
console.log(disabledElements); // {}
})
</script>
</body>
</html>
这是一个简单的 HTML 页面,其中包含一个按钮和一个事件监听器。在点击按钮后,事件监听器会从页面中删除按钮,并使用 WeakSet
来记录已经被禁用的按钮。
让我解释一下代码:
-
HTML 结构:
html<div id="wrap"> <button id="btn">确认</button> </div>
这是一个包含一个按钮的简单页面。
-
JavaScript 代码:
jslet wrap = document.getElementById('wrap'); let btn = document.getElementById('btn');
这两行代码获取了页面中的
wrap
元素和btn
按钮。jsconst disabledElements = new WeakSet() disabledElements.add(btn)
这里创建了一个
WeakSet
,名为disabledElements
,用于存储已被禁用的元素。然后,将按钮btn
添加到disabledElements
中,表示该按钮已经被禁用。jsbtn.addEventListener('click', () => { wrap.removeChild(btn) console.log(disabledElements); // {} })
这段代码添加了一个点击事件监听器,当按钮被点击时,它会从父元素
wrap
中移除按钮btn
。然后,打印disabledElements
,你会发现在控制台输出一个空的对象{}
。这是因为按钮被移除后,它的引用从disabledElements
中被移除,WeakSet
不会阻止按钮被垃圾回收,因此disabledElements
变为空。使用WeakSet
来追踪已经被禁用的元素,而不会阻止这些元素被垃圾回收。
总结
WeakSet
是 JavaScript 中的一种集合类型,具有以下主要特点:
- 弱引用:
WeakSet
中存储的是对象的弱引用。这意味着,如果在程序中没有其他强引用指向集合中的对象,这些对象可能会被垃圾回收器回收,即使它们存在于WeakSet
中。 - 只能包含对象:
WeakSet
只能包含对象,而不能包含原始值(如字符串、数字等)。 - 不可迭代:
WeakSet
不具备迭代的能力,因此不能使用类似forEach
的方法直接访问其元素。这是为了避免暴露可能已经被垃圾回收的对象。 - 有限的方法:
WeakSet
具有有限的方法,主要包括add(obj)
、has(obj)
和delete(obj)
。没有类似size
属性或forEach
方法这样的集合大小或迭代的功能。 - 不阻止垃圾回收: 与普通对象引用不同,
WeakSet
不会阻止其元素被垃圾回收。当集合中的对象失去其他强引用时,这些对象可能会被垃圾回收器回收。 - 适用于临时存储: 由于
WeakSet
不会阻止对象被垃圾回收,它通常用于需要临时存储对象引用的情况,而不希望影响对象的生命周期。 - 不能清空: 与
Set
不同,WeakSet
没有提供直接清空所有元素的方法。如果需要清空,必须放弃对整个WeakSet
对象的引用,以便垃圾回收器将其清理。