Часто возникают требования, когда нам нужно создать карту, которая однозначно идентифицирует сегменты на основе значения ключа. У нас уже есть эта структура практически на любом языке, о котором мы только можем подумать. Например, в Java есть хорошо известная HashMap, которая хранит данные в сегментах, и каждый сегмент располагается по значению своего ключа.
Карты в JavaScript немного отличаются. Хоть они и созданы для того, чтобы нам было удобно хранить объекты в качестве ключей, но есть проблема. Предположим, что есть два объекта с одинаковыми свойствами.
let object1 = { name: "abc", age: 25 } let object2 = { name: "abc", age: 25 }
Теперь мы можем подумать о добавлении этих объектов в качестве ключа на карту, как показано ниже.
let ourMap = new Map(); ourMap.set(object1, "some value"); ourMap.set(object2, "this value should be updated");
В полученной карте у нас будет создано два разных ключа.
Это проблема, если мы хотим, чтобы карта рассматривала ключи, имеющие объекты с одинаковыми значениями, как равные.
Решение: используйте символы
Symbol — это недавно появившийся примитивный тип данных, добавленный в JavaScript. Обратите внимание, что тип данных Symbol не является типом объекта, а является примитивным.
Мы создаем символы, как показано ниже
let sym = Symbol(); let symWithDescription = Symbol("this is a description");
Обратите внимание, что новое ключевое слово не используется, как в случае с объектами.
Символы имеют специальный ключ, связанный с каждым из них. Мы можем создать символ для определенного ключа, используя его метод for().
let symFor123 = Symbol.for(123);
Сначала JavaScript проверяет, создан ли символ для ключа 123, и только если такой символ не создан, он создает новый.
Обратите внимание, что Symbol(123) — это не то же самое, что Symbol.for(123).
Параметр конструктора является только описанием символа в случае Symbol(123), тогда как в случае Symbol.for(123) мы создаем символ для ключа 123
console.log(Symbol(123) == Symbol.for(123)); //false console.log(Symbol(123) === Symbol.for(123)); //false
Теперь у нас есть решение иметь уникальные ключи на нашей карте на основе свойств объекта. Нам просто нужно создать символы для объектов!
let object1 = { name: "abc", age: 25 } let object2 = { name: "abc", age: 25 } console.log(Symbol.for(object1) == Symbol.for(object2)); //true
JavaScript будет считать, что Symbol уже создан для объекта, имеющего одинаковые пары ключ-значение свойств. Таким образом, новый символ не будет создан при выполнении Symbol.for(object2).
Использование вышеуказанной концепции в нашей карте
let object1 = { name: "abc", age: 25 } let object2 = { name: "abc", age: 25 } let ourMap = new Map(); ourMap.set(Symbol.for(object1), "some value"); ourMap.set(Symbol.for(object2), "this value should be updated");
Теперь наша карта будет иметь только одну пару ключ-значение в конце. Поскольку мы используем символ в качестве ключа для карты, вторая операция набора просто обновит значение для этого ключа.
Подробнее о символах читайте здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
Дайте мне знать, если у вас есть какие-либо отзывы.
Спасибо!