Этот пост о Symbol()
, снабженный фактическими примерами, которые я мог найти / сделать, и фактами и определениями, которые я мог найти.
TLDR;
Тип Symbol()
данных, представленный в выпуске ECMAScript 6 (ES6).
Есть два любопытных факта о Символе.
первый тип данных и единственный тип данных в JavaScript, который не имеет литерала
любая переменная, определенная с помощью Symbol()
, получает уникальный контент, но на самом деле он не является частным .
любые данные имеют свой собственный символ, и для тех же данных символы будут одинаковыми . Больше информации в следующем параграфе, иначе это не TLRD; :)
Как мне инициализировать символ?
1. Получить уникальный идентификатор с отладочным значением
Вы можете сделать это так:
var mySymbol1 = Symbol();
Или так:
var mySymbol2 = Symbol("some text here");
"some text here"
Строка не может быть извлечена из символа, это просто описание для целей отладки. Это никак не меняет поведение символа. Хотя, вы могли бы console.log
это сделать (что справедливо, поскольку значение используется для отладки, чтобы не перепутать этот журнал с какой-либо другой записью журнала):
console.log(mySymbol2);
// Symbol(some text here)
2. Получить символ для некоторых строковых данных
В этом случае значение символа фактически учитывается, и таким образом два символа могут быть неуникальными.
var a1 = Symbol.for("test");
var a2 = Symbol.for("test");
console.log(a1 == a2); //true!
Давайте назовем эти символы символами второго типа. Они никак не пересекаются с символами «первого типа» (т. Е. Теми, которые определены с помощью Symbol(data)
).
Следующие два абзаца относятся только к символу первого типа .
Как извлечь выгоду из использования Symbol вместо старых типов данных?
Давайте сначала рассмотрим объект, стандартный тип данных. Мы могли бы определить несколько пар ключ-значение и получить доступ к значениям, указав ключ.
var persons = {"peter":"pan","jon":"doe"};
console.log(persons.peter);
// pan
Что если у нас есть два человека с именем Питер?
Делая это:
var persons = {"peter":"first", "peter":"pan"};
не имеет особого смысла.
Таким образом, возникает проблема двух абсолютно разных людей, имеющих одинаковые имена. Давайте тогда ссылаться на новое Symbol()
. Это как человек в реальной жизни - любой человек уникален , но его имена могут быть одинаковыми. Давайте определим два «человека».
var a = Symbol("peter");
var b = Symbol("peter");
Теперь у нас есть два разных человека с одинаковыми именами. Наши люди действительно разные? Они есть; Вы можете проверить это:
console.log(a == b);
// false
Какую пользу мы получаем там?
Мы можем сделать две записи в вашем объекте для разных людей, и они не могут быть ошибочно приняты.
var firstPerson = Symbol("peter");
var secondPerson = Symbol("peter");
var persons = {[firstPerson]:"first", [secondPerson]:"pan"};
Примечание.
Следует отметить, что при приведении объекта в JSON.stringify
порядок все пары, инициализированные символом в качестве ключа, будут отброшены.
Выполнение Object.keys
также не вернет такие Symbol()->value
пары.
Используя эту инициализацию, абсолютно невозможно перепутать записи для первого и второго лица. Вызов console.log
для них правильно выведет их вторые имена.
console.log(persons[a]);
// first
console.log(persons[b]);
// pan
Когда он используется в объекте, чем он отличается от определения не перечислимого свойства?
Действительно, уже существовал способ определения свойства, от которого необходимо скрыть, Object.keys
и перечисления. Вот:
var anObject = {};
var fruit = "apple";
Object.defineProperty( anObject, fruit, {
enumerable: false,
value: "green"
});
Какая разница Symbol()
? Разница в том, что вы все еще можете получить свойство, определенное Object.defineProperty
обычным способом:
console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //green
console.log(anObject.apple); //green
И если определено с символом, как в предыдущем абзаце:
fruit = Symbol("apple");
У вас будет возможность получить его значение, только если вы знаете его переменную, т.е.
console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //undefined
console.log(anObject.apple); //undefined
Более того, определение другого свойства под ключом "apple"
приведет к тому, что объект отбросит более старое (и если его жестко закодировать, это может привести к ошибке). Так что, яблок больше нет! Какая жалость. Ссылаясь на предыдущий абзац, символы являются уникальными и определяют ключ, Symbol()
который сделает его уникальным.
Преобразование типов и проверка
В отличие от других типов данных, невозможно преобразовать их Symbol()
в любой другой тип данных.
Можно «сделать» символ, основанный на примитивном типе данных, путем вызова Symbol(data)
.
С точки зрения проверки типа ничего не меняется.
function isSymbol ( variable ) {
return typeof someSymbol === "symbol";
}
var a_Symbol = Symbol("hey!");
var totally_Not_A_Symbol = "hey";
console.log(isSymbol(a_Symbol)); //true
console.log(isSymbol(totally_Not_A_Symbol)); //false