WeakSet

Последнее обновление: 26.10.2023

Объект WeakSet во многом похож на обычное множество. Он также может хранить только уникальные значения, но каждый его элемент должен представлять объект.

Для создания объекта WeakSet используется его конструктор, в который можно передать начальные значения:

// пустой WeakSet
const weakSet1 = new WeakSet();
// инициализация начальными значениями
const weakSet2 = new WeakSet([{name:"Tom", age: 37}, {name:"Alice", age: 34}]);

Для инициализации как в случае с объектом Set в конструктор передается массив, но данный массив содержит именно объекты, а не скалярные значения, типа чисел или строк.

Для добавления данных в WeakSet применяется метод add():

const weakSet = new WeakSet();
weakSet.add({lang: "JavaScript"});
weakSet.add({lang: "TypeScript"});
// weakSet.add(34);	// так нельзя - 34 - число, а не объект
console.log(weakSet);	// {{lang: "JavaScript"}, {lang: "TypeScript"}}

Причем опять же добавить мы можем только объект, а не скалярные значения типа чисел или строк.

Для удаления применяется метод delete(), в который передается ссылка на удаляемый объект:

const weakSet = new WeakSet();
const js = {lang: "JavaScript"};
const ts = {lang: "TypeScript"};
weakSet.add(js);
weakSet.add(ts);

weakSet.delete(js);

console.log(weakSet);	// {{lang: "TypeScript"}}

Если надо проверить, имеется ли объект в WeakSet, то можно использовать метод has(), который возвращает true при наличии объекта:

const js = {lang: "JavaScript"};
const ts = {lang: "TypeScript"};
const java = {lang: "Java"};
const weakSet = new WeakSet([js, ts]);
console.log(weakSet.has(ts));		// true
console.log(weakSet.has(java));		//  false

Перебор WeakSet

Стоит отметить, что WeakSet не поддерживает перебор ни с помощью метода ForEach, которого у WeakSet нет, ни с помощью цикла for. Например. если мы попробуем перебрать WeakSet через цикл for..of:

const weakSet = new WeakSet([
	{lang: "JavaScript"}, 
	{lang: "TypeScript"}, 
	{lang: "Java"}
]);


for(item of weakSet){
	console.log(item);
}

То мы получим ошибку

Uncaught TypeError: weakSet is not iterable

Слабые ссылки

Объекты передаются в WeakSet по ссылке. И отличительной особенностью WeakSet является то, что когда объект перестает существовать в силу различных причин, он удаляется из WeakSet. Так, рассмотрим следующий пример:

let js = {lang: "JavaScript"};
let ts = {lang: "TypeScript"};
const weakSet = new WeakSet([js, ts]);

js = null;

console.log(weakSet);	// {{lang: "JavaScript"}, {lang: "TypeScript"}}
console.log("Некоторая работа");
const timerId = setTimeout(function(){
	console.log(weakSet);	// {{lang: "TypeScript"}}
	clearTimeout(timerId);
}, 20000);

В данном случае сначала объект WeakSet хранит ссылки на два объекта: js и ts. Далее мы устанавливаем значение для переменной js в null.

Это приведет к тому, что спустя некоторое время начальное значение этой переменной будет удалено сборщиком мусора JavaScript.

js = null;

Причем если сразу после этого мы посмотрим на содержимое weakSet, то увидим, что объект js в нем еще присутствует. Однако спустя некоторое время ссылка будет удалена из weakSet. Для эмуляции прошествия времени здесь используется функция setTimeout, которая выводит на консоль содержимое weakSet через 9000 секунд (конкретный период времени, через который сборщик мусора удалит значение, может отличаться)

Теперь сравним с тем, что произойдет, если вместо WeakSet использовать Set:

let js = {lang: "JavaScript"};
let ts = {lang: "TypeScript"};
const set = new Set([js, ts]);

js = null;

console.log(set);	// Set(2) {{lang: "JavaScript"}, {lang: "TypeScript"}}
console.log("Некоторая работа");
const timerId = setTimeout(function(){
	console.log(set);	// Set(2){{lang: "JavaScript"}, {lang: "TypeScript"}}
	clearTimeout(timerId);
}, 20000);

В случае с Set даже спустя некоторое время мы увидим, что в объекте Set до сих пор присутствует объект, для которого было установлено значение null

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850