Часто возникают требования, когда нам нужно создать карту, которая однозначно идентифицирует сегменты на основе значения ключа. У нас уже есть эта структура практически на любом языке, о котором мы только можем подумать. Например, в 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

Дайте мне знать, если у вас есть какие-либо отзывы.

Спасибо!