Каковы возможные сценарии использования нового типа данных "Символ" JavaScript?

Я просто наткнулся на документацию для нового (предлагаемого для ES6, но уже реализованного в Firefox, Chrome и Opera) типа данных в JavaScript, Symbol:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol http://people.mozilla.org/~jorendorff/es6-draft.html#sec-symbol-objects

Я читаю об этом, но я просто не могу думать о возможном сценарии использования.

В документации написано:

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

ОК, хорошо, скажем, я делаю, как говорится в документации:

obj[Symbol("a")] = "a";

но поскольку Symbol ('a') всегда возвращает уникальное значение (объект) и:

Символы не отображаются для... в итерациях.

Как получить мое свойство из obj?

var obj = { normalProperty: 'just a string' };
obj[Symbol('a')] = 'a';

document.getElementById('retrieve').addEventListener('click', function() {
  document.write('Stringified object:' + JSON.stringify(obj) + '<br/><br/>');
  document.write('Trying to get Symbol-property value, aaaand...: <br/>');
  document.write(obj[Symbol('a')]); // undefined
}, false);
<button id="retrieve">Retrieve obj property</button>

Ответ 1

Прочитав документацию и немного сыграв с этим типом Symbol в chrome, кажется, что Symbol - это способ определить имя, а не значение, и тот факт, что свойства, определенные с помощью символы не видны с помощью for..in, Object.getOwnPropertyNames() или JSON.stringify() делает символы полезными для свойств метаданных:

// define metadata symbols
var Metadata = {
        Date: Symbol('Message date')
};

var email = function(recipient, message) {
    this.Recipient = recipient;
    this.Message = message;
    this[Metadata.Date] = new Date();
};

var email1 = new email('@Me', 'test');
JSON.stringify(email1);
// {
//    Recipient: '@Me',
//    Message: 'test'
// }

// Date is still accessible using
email1[Metadata.Date];
// Thu Nov 27 2014 16:50:00 GMT+0000

// Debugging in Console:
// {
//    Recipient: '@Me',
//    Message: 'test'
//    Symbol(Message date): Thu Nov 27 2014 16:50:00 GMT+0000
// }

Символы могут быть сделаны глобальными с помощью функции Symbol.for, поэтому имена метаданных могут быть созданы один раз и использоваться во всех файлах проекта.

Доступ к значению с использованием символа требует наличия ссылки на символ при создании. Каждый вызов Symbol() создает новый, даже если используется одно и то же описание:

var a = Symbol('a');
var b = Symbol('a');
a != b
// and
a != Symbol('a')

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

var a = Symbol.for('a');
var b = Symbol.for('a');
a == b
// and
a == Symbol.for('a')

Ответ 2

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

Посмотрите на мой пример

const bert = Symbol('Bert');

'Берт'

Примечание: это не значение, это то, что они назвали дескриптором, потому что сам символ является просто уникальным идентификатором. Так что, если бы вы визуализировали, каким будет символ, возможно, вы сможете визуализировать его примерно как этот "sdfasdfa2342134987fgsdfgsdf9808fsfgsd" абсолютный уникальный символ, так что вы можете быть уверены, что он никогда не заменит любой другой фрагмент кода в нем.

Что круто в этом, если я создаю второй символ, например

const person = Symbol('Bert')

Вы можете видеть, что я снова использовал "Берт". Будут ли они такими же, потому что я описал их как одно и то же?

const bert = Symbol('Bert');
const person = Symbol('Bert');


console.log(bert);
console.log(person);
console.log(bert === person);
console.log(bert == person);