Каковы возможные сценарии использования нового типа JavaScript "Symbol"?
Я просто наткнулся на документацию для нового (предложенного для 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
Я читаю об этом, но я просто не могу придумать возможный сценарий использования.
В документации сказано:
Символ является уникальным и неизменным типом данных и может использоваться в качестве идентификатора для свойств объекта.
Хорошо, хорошо, допустим, я делаю так, как написано в документации:
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's property</button>
редактировать
Конечно, вы можете получить его так:
var x = Symbol('a');
obj[x] = 'a';
obj[x]; // "a"
но какова цель сделать это таким образом?
Заранее спасибо:)
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')
Они в значительной степени помогают нам иметь конфликты имен. В любое время, когда вы хотите создать свойство уникальным способом, вы должны обратиться к символу.
Посмотрите на мой пример
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);
Это может быть полезно, если вы создаете объект своего класса.
const classRoom = {
'Mia' : { grade: 50, gender: 'female' },
'Gilbert': { grade: 80, gender: 'male' },
'Gilbert' { grade: 80, gender: 'male' },
};
Но тогда у вас есть еще один по имени Гилберт, так что вы столкнулись с именами. Так что представьте, если вы работаете с миллионами и миллионами данных. Таким образом, вместо того, чтобы использовать имя людей или использовать какой-то уникальный идентификатор, мы можем использовать символ для их имен.
const classRoom = {
[Symbol('Mia')] : { grade: 50, gender: 'female' },
[Symbol('Gilbert')]: { grade: 80, gender: 'male' },
[Symbol('Gilbert')]: { grade: 80, gender: 'male' },
};
Еще одна вещь, связанная с символами, заключается в том, что они не перечисляются, а это означает, что мы не можем зациклить их, если бы я
for (const person in classRoom) {
console.log(person);
}
Я ничего не получаю.
Если вы хотите получить доступ ко всем вашим символам, потому что они содержат некоторую информацию, которую вы хотите получить, вы можете использовать метод объекта.
const syms = Object.getOwnPropertySymbols(classRoom);
const data = syms.map(sym => classRoom[sym]);
console.log(data);