Символы (Symbols)

Symbol — это новый примитивный тип. Главная вещь которую он предоставляет — уникальный идентификатор.

Прикол в том, что вы не видите сам идентификатор. У вас есть только символ, то есть у вас нет ключа вида dd3924809x. У вас просто есть символ, и вы знаете что он предоставляет уникальный идентификатор.

Символы не итерабельны. Что значит, что если вы попробуйте пройтись по объекту с помощью for-in loop, что вы не увидите свойтва объекта, заданные через символы.

Symbol basic

Давайте создадим символ. Он создается без оператора new и принимает один аргумент, который больше предназначен для дебаггинга, чем для работы.

let symbol = Symbol("debug");
console.log(symbol);

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

let symbol = Symbol("debug");
let obj = {
  id: Symbol(),
  name: "max",
  [symbol]: 22
};

console.log(obj[symbol]); //22

Shared Symbols

Есть еще один способ создавать символы. Если Вам нужно несколько символов, которые ссылаются на один и тот же айди, то вы можете создать символы следующим способом

let symbol1 = Symbol.for("age");
let symbol2 = Symbol.for("age");
console.log(symbol1 == symbol2);

let person = {
  name: "Eugene"
};

function mageAge(person) {
  let ageSymbol = Symbol.for("age");
  person[ageSymbol] = 27;
}

makeAge(person);

console.log(person[symbol1]);

Еще один пример, почему символы нужные. Допустим у персонажа Eugene уже было свойство age. Мы получим разные значения всё равно.

let symbol1 = Symbol.for("age");
let symbol2 = Symbol.for("age");
console.log(symbol1 == symbol2);

let person = {
  name: "Eugene",
  age: 30
};

function mageAge(person) {
  let ageSymbol = Symbol.for("age");
  person[ageSymbol] = 27;
}

makeAge(person);

console.log(person[symbol1]); //27
console.log(person["age"]); //30

Предустановленные символы

Есть так называемые well-known символы, которые уже имплементированы и предоставляют некоторую функциональность на конкретных объектах. Посмотрим на пример.

class Person {}
const person = new Person();
console.log(person);

Консоль выведет нам [object Object], что показывает нам что это объект типа объект ). Эта функция, которая выводит эту инфу встроена в toSting() метод. Мы можем переписать этот функционал с помощью symbol. У него есть некоторый набор статических полей, к которым у нас есть доступ.

Person.prototype[Symbol.toStringTag] = `Person`;
console.log(person); // [object Person]

Есть и другие символы такого рода. Лучший способ найти их — это загуглить es6 well known symbols.

let numbers = [1, 2, 3];
console.log(numbers + 1); //"1,2,31"

Но мы можем изменить такой вывыод

let numbers = [1, 2, 3];
numbers[Symbol.toPrimitive] = function() {
  return this.reduce((prev, cur) => {
    return prev + cur;
  });
};

console.log(numbers + 1); //7