Описание темы:
Покажите разницу между Set, Map, WeakSet и WeakMap?
Решение проблем:
- Идея первая:
Основные сценарии применения Set и Map:реорганизация данныха такжехранилище данных
Set — это структура данных, называемая коллекцией, Map — это структура данных, называемая словарем.
1 комплект
В ES6 добавлена новая структура данных, похожая на массив, но члены уникальны и неупорядочены, без повторяющихся значений.
Сам Set является конструктором, который генерирует структуру данных Set.
new Set([iterable])
Например:
const s = new Set()
[1, 2, 3, 4, 3, 2, 1].forEach(x => s.add(x))
for (let i of s) {
console.log(i) // 1 2 3 4
}
// 去重数组的重复对象
let arr = [1, 2, 3, 2, 1, 1]
[... new Set(arr)] // [1, 2, 3]
Объекты Set позволяют хранить уникальные значения любого типа, будь то примитивные значения или ссылки на объекты.
При добавлении значений в Set не происходит преобразования типов, поэтому 5 и «5» — это два разных значения. Set внутренне определяет, различаются ли два значения.Используемый алгоритм называется «равенство одинакового значения-нуля», который аналогичен оператору точного равенства (===), основное отличиеNaN равен самому себе, в то время как оператор точного равенства считает NaN не равным самому себе.
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set // Set {NaN}
let set1 = new Set()
set1.add(5)
set1.add('5')
console.log([...set1]) // [5, "5"]
- Установить свойства экземпляра
конструктор: конструктор
размер: количество элементов
let set = new Set([1, 2, 3, 2, 1])
console.log(set.length) // undefined
console.log(set.size) // 3
- Установить методы экземпляра
Метод операции add(value): новый, эквивалентный вставке в массив
delete(value):存在即删除集合中value
has(value):判断集合中是否存在 value
clear():清空集合
let set = new Set()
set.add(1).add(2).add(1)
set.has(1) // true
set.has(3) // false
set.delete(1)
set.has(1) // false
Метод Array.from может преобразовать структуру Set в массив
const items = new Set([1, 2, 3, 2])
const array = Array.from(items)
console.log(array) // [1, 2, 3]
// 或
const arr = [...items]
console.log(arr) // [1, 2, 3]
Метод обхода (порядок обхода — это порядок вставки)
keys():返回一个包含集合中所有键的迭代器
values():返回一个包含集合中所有值得迭代器
ntries():返回一个包含Set对象中所有元素得键值对迭代器
forEach(callbackFn, thisArg):用于对集合成员执行callbackFn操作,如果提供了 thisArg 参数,回调中的this会是这个参数,没有返回值
let set = new Set([1, 2, 3])
console.log(set.keys()) // SetIterator {1, 2, 3}
console.log(set.values()) // SetIterator {1, 2, 3}
console.log(set.entries()) // SetIterator {1, 2, 3}
for (let item of set.keys()) {
console.log(item);
} // 1 2 3
for (let item of set.entries()) {
console.log(item);
} // [1, 1] [2, 2] [3, 3]
set.forEach((value, key) => {
console.log(key + ' : ' + value)
}) // 1 : 1 2 : 2 3 : 3
console.log([...set]) // [1, 2, 3]
Набор может быть пройден по умолчанию, а функция генерации итератора по умолчанию — это метод values().
Set.prototype[Symbol.iterator] === Set.prototype.values // true
Итак, Set может использовать методы отображения и фильтрации.
let set = new Set([1, 2, 3])
set = new Set([...set].map(item => item * 2))
console.log([...set]) // [2, 4, 6]
set = new Set([...set].filter(item => (item >= 4)))
console.log([...set]) //[4, 6]
Следовательно, набор прост в реализации пересечения (пересекается), союз (союз), установленная разница (разница)
let set1 = new Set([1, 2, 3])
let set2 = new Set([4, 3, 2])
let intersect = new Set([...set1].filter(value => set2.has(value)))
let union = new Set([...set1, ...set2])
let difference = new Set([...set1].filter(value => !set2.has(value)))
console.log(intersect) // Set {2, 3}
console.log(union) // Set {1, 2, 3, 4}
console.log(difference) // Set {1}
2. WeakSet
Объекты WeakSet позволяют хранить объекты со слабыми ссылками в коллекции.
Разница между WeakSet и Set:
- WeakSet может хранить только ссылки на объекты, но не значения, в то время как объекты Set могут
- Все значения объекта, хранящиеся в объекте WeakSet, слабо ссылаются, то есть механизм сборки мусора не учитывает применение WeakSet к объекту.Если никакие другие переменные или атрибуты не ссылаются на значение объекта, объект будет сбор мусора (не учитывая, что объект все еще существует в WeakSet), поэтому количество элементов-членов в объекте WeakSet зависит от того, запущен механизм сборки мусора или нет.Количество элементов до и после запуска может быть непоследовательным. После завершения обхода некоторые элементы могут быть недоступны (сборщик мусора), объект WeakSet не может быть пройден (ES6 оговаривает, что WeakSet не может быть пройден), и нет возможности получить все содержащиеся в нем элементы
Атрибут: конструктор: конструктор, любой объект с интерфейсом Iterable может быть использован в качестве параметра
const arr = [[1, 2], [3, 4]]
const weakset = new WeakSet(arr)
console.log(weakset)
// {[1,2], [3,4]}
метод:
- add(value): добавить значение элемента в объект WeakSet.
- has(value): определить, содержит ли объект WeakSet значение
- удалить (значение): удалить значение элемента
- clear(): очищает все элементы, обратите внимание, что этот метод устарел
var ws = new WeakSet()
var obj = {}
var foo = {}
ws.add(window)
ws.add(obj)
ws.has(window) // true
ws.has(foo) // false
ws.delete(window) // true
ws.has(window) // false
3. Словарь (Карта)
Разница между набором и словарем:
- Точка соприкосновения: наборы, словари могут хранить уникальные значения
- Разница: наборы хранят элементы в форме [значение, значение], а словари хранят элементы в форме [ключ, значение].
const m = new Map()
const o = {p: 'haha'}
m.set(o, 'content')
m.get(o) // content
m.has(o) // true
m.delete(o) // true
m.has(o) // false
Любая структура данных с интерфейсом Iterator, где каждый элемент представляет собой массив из двух элементов, может использоваться в качестве аргумента для конструктора Map, например:
const set = new Set([
['foo', 1],
['bar', 2]
]);
const m1 = new Map(set);
m1.get('foo') // 1
const m2 = new Map([['baz', 3]]);
const m3 = new Map(m2);
m3.get('baz') // 3
Возвращает значение undefined, если считывается неизвестный ключ.
new Map().get('asfddfsasadf')
// undefined
Обратите внимание, что только ссылки на один и тот же объект считаются одним и тем же ключом в структуре Map. Будьте очень осторожны с этим.
const map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
Методы set и get приведенного выше кода кажутся для одного и того же ключа, но на самом деле это два значения, а адреса памяти разные, поэтому метод get не может прочитать ключ и возвращает значение undefined.
Из вышеизложенного видно, что ключ карты фактически привязан к адресу памяти, и пока адреса памяти разные, он рассматривается как два ключа. Это решает проблему конфликта атрибутов с тем же именем.Когда мы расширяем чужие библиотеки, если мы используем объект в качестве имени ключа, нам не нужно беспокоиться о том, что наш собственный атрибут имеет то же имя, что и исходный авторский атрибут.
Если ключ Карты является значением простого типа (число, строка, логическое значение), то до тех пор, пока два значения строго равны, Карта рассматривает его как ключ, например 0 и -0 — это key, boolean true и character Строка true — это два разных ключа. Кроме того, undefined и null — это два разных ключа. Хотя NaN не является строго равным самому себе, Map рассматривает его как один и тот же ключ.
let map = new Map();
map.set(-0, 123);
map.get(+0) // 123
map.set(true, 1);
map.set('true', 2);
map.get(true) // 1
map.set(undefined, 3);
map.set(null, 4);
map.get(undefined) // 3
map.set(NaN, 123);
map.get(NaN) // 123
Свойства и методы карты
Атрибуты:
- конструктор: конструктор
- размер: возвращает количество элементов, содержащихся в словаре
const map = new Map([
['name', 'An'],
['des', 'JS']
]);
map.size // 2
Метод работы:
- set(key, value): добавить новый элемент в словарь
- get(key): найти конкретное значение по ключу и вернуть
- has(key): определить, существует ли ключ key в словаре
- delete(key): удалить соответствующие данные из словаря по клавише key
- clear(): удалить все элементы в этом словаре
метод обхода
- Keys(): возвращает все имена ключей, содержащиеся в словаре, в качестве итератора.
- values(): возвращает все значения, содержащиеся в словаре, как итератор
- entry(): возвращает итератор всех членов
- forEach(): перебирает все элементы словаря.
const map = new Map([
['name', 'An'],
['des', 'JS']
]);
console.log(map.entries()) // MapIterator {"name" => "An", "des" => "JS"}
console.log(map.keys()) // MapIterator {"name", "des"}
Интерфейс итератора по умолчанию (свойство Symbol.iterator) структуры Map — это метод entry.
map[Symbol.iterator] === map.entries
// true
Более быстрый способ преобразовать структуру карты в структуру массива — использовать оператор распространения (...).
Для forEach см. пример
const reporter = {
report: function(key, value) {
console.log("Key: %s, Value: %s", key, value);
}
};
let map = new Map([
['name', 'An'],
['des', 'JS']
])
map.forEach(function(value, key, map) {
this.report(key, value);
}, reporter);
// Key: name, Value: An
// Key: des, Value: JS
В этом примере this функции обратного вызова метода forEach указывает на репортер
Взаимное преобразование с другими структурами данных
1. Карта в массив
const map = new Map([[1, 1], [2, 2], [3, 3]])
console.log([...map]) // [[1, 1], [2, 2], [3, 3]]
2. Массив для отображения
const map = new Map([[1, 1], [2, 2], [3, 3]])
console.log(map) // Map {1 => 1, 2 => 2, 3 => 3}
3. Сопоставьте объект
Поскольку все имена ключей Object являются строками, а имена ключей Map являются объектами, нестроковые имена ключей будут преобразованы в имена строковых ключей во время преобразования.
function mapToObj(map) {
let obj = Object.create(null)
for (let [key, value] of map) {
obj[key] = value
}
return obj
}
const map = new Map().set('name', 'An').set('des', 'JS')
mapToObj(map) // {name: "An", des: "JS"}
4.Объект на карту
function objToMap(obj) {
let map = new Map()
for (let key of Object.keys(obj)) {
map.set(key, obj[key])
}
return map
}
objToMap({'name': 'An', 'des': 'JS'}) // Map {"name" => "An", "des" => "JS"}
5. Сопоставьте с JSON
function mapToJson(map) {
return JSON.stringify([...map])
}
let map = new Map().set('name', 'An').set('des', 'JS')
mapToJson(map) // [["name","An"],["des","JS"]]
6. JSON для сопоставления
function jsonToStrMap(jsonStr) {
return objToMap(JSON.parse(jsonStr));
}
jsonToStrMap('{"name": "An", "des": "JS"}') // Map {"name" => "An", "des" => "JS"}
4. WeakMap
Объект WeakMap — это набор пар ключ-значение, где ключи являются слабыми эталонными объектами, а значения могут быть произвольными.
Обратите внимание, что WeakMap слабо ссылается только на имена ключей, а не на их значения. Значение ключа по-прежнему является обычной ссылкой.
В WeakMap ссылка каждого ключа на объект, на который он указывает, является слабой ссылкой.Если никакая другая ссылка не ссылается на тот же объект, что и ключ, объект будет удален сборщиком мусора (соответствующий ключ станет недействительным), поэтому WeakMap ключ не перечисляемый.
Атрибуты:
- конструктор: конструктор
метод:
- has(key): определить, есть ли связанный с ключом объект
- get(key): возвращает объект, связанный с ключом (если нет, возвращает undefined)
- set(key): Установить набор ключевых связанных объектов
- удалить (ключ): удалить связанный объект ключа
let myElement = document.getElementById('logo');
let myWeakmap = new WeakMap();
myWeakmap.set(myElement, {timesClicked: 0});
myElement.addEventListener('click', function() {
let logoData = myWeakmap.get(myElement);
logoData.timesClicked++;
}, false);
- Set
- Члены являются уникальными, неупорядоченными и неповторяющимися
- [значение, значение], значение ключа совпадает с именем ключа (или только значение ключа, без имени ключа)
- Его можно пройти, методы: добавить, удалить, имеет
- WeakSet
- члены являются объектами
- Члены — это слабые ссылки, которые могут быть переработаны механизмом сборки мусора и могут использоваться для сохранения узлов DOM, что не так просто вызвать утечку памяти.
- Невозможно пройти, методы добавляются, удаляются, есть
- Map
- По сути это набор пар ключ-значение, похожий на набор
- Его можно пройти, и есть много методов, которые можно преобразовать с различными форматами данных.
- WeakMap
- В качестве ключей принимает только объекты (кроме null), и не принимает в качестве ключей другие типы значений
- Имя ключа является слабой ссылкой, значение ключа может быть произвольным, объект, на который указывает имя ключа, может быть удален сборщиком мусора, а имя ключа в настоящее время недопустимо.
Невозможно пройти, методы get, set, has, delete
6. Расширение: объект и набор, карта
1. Объект и набор
// Object
const properties1 = {
'width': 1,
'height': 1
}
console.log(properties1['width']? true: false) // true
// Set
const properties2 = new Set()
properties2.add('width')
properties2.add('height')
console.log(properties2.has('width')) // true
2. Объект и карта
Объект (Object) в JS по сути представляет собой набор пар ключ-значение (хэш-структура)
const data = {};
const element = document.getElementsByClassName('App');
data[element] = 'metadata';
console.log(data['[object HTMLCollection]']) // "metadata"
Но когда DOM-узел используется в качестве ключа данных объекта, объект будет автоматически преобразован в строку [Object HTMLCollection], поэтому структура Object обеспечивает соответствие строка-значение, а Map обеспечивает соответствие значение-значение.
- Вторая идея? :
:point_down:~~~~ Добро пожаловать в **дополнение комментария** к вашему ответу ниже, давайте учиться вместе~ :pushpin:
Дальнейшее чтение:
- Новые функции ES2018, которые должны знать квалифицированные разработчики JS
- Установить и сопоставить структуры данных
- 15 000 слов, описывающих все возможности ES6
❤️ После прочтения двух мелочей
Если вы найдете эту статью вдохновляющей, я хотел бы попросить вас сделать мне два небольших одолжения:
Поделитесь этой статьей со своими друзьями/группой общения, чтобы больше людей могли ее увидеть, добиться прогресса и расти вместе!
Обратите внимание на общественный номер»ИТ-альянс Flathead", официальный ответ за кулисами аккаунта "资源
” Получите мои тщательно организованные расширенные учебные пособия по внешним ресурсам бесплатно
JS Китайская сеть - опытные учебные пособия на переднем углуwww.javascriptC.com
Платформа, призванная помочь разработчикам изменить мир с помощью кода, где вы можете каждый день узнавать заголовки мира технологий.
![JS Chinese Network — Учебное пособие по расширенным ресурсам переднего плана](https://www.javascriptc.com)