Translate

Поиск по этому блогу

пятница, 28 сентября 2018 г.

ES6: Символы (symbols) (XV).

Symbol

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

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



Все материалы по ES6


Символы - уникальные и неизменные значения.

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

В основном символы используются внутри языка JavaScript и вам вряд ли придется часто с ними работать.

Давайте перейдем в редактор и посмотрим как создаются и используются символы.

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

Пройти по пути сайт Babel -> Usage ->Polyfill



Установить через npm в папку проекта и подключить в файле index.html

<script src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>

Откроем в редакторе файл symbol.js, подключим его к нашему файлу index.html, точно так же, как мы это делали в предыдущих частях руководства.

<script src="src/symbol.js"></script>

Создание символов

Создадим переменную и в нее пометим результат вызова функции Symbol.

Результат выведем в консоль.


let symbol = Symbol();

console.log(symbol);



Посмотрим в консоль



Давайте посмотрим на тип переменной symbol используя оператор typeof.


let symbol = Symbol();

console.log( typeof symbol);





Заметьте, что при создании нового символа мы не используем слово new.

Если мы, все таки попробуем, то получим ошибку.


let symbol = new Symbol();

console.log( typeof symbol);





Это происходит потому, что Symbol не является конструктором.

У функции Symbol() есть необязательный аргумент, с помощью которого мы можем указать имя символа, что может быть полезно при отладке.


let symbol = Symbol('name');

console.log(symbol);





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


let symbol = Symbol('name');
let symbol2 = Symbol('name');

console.log(symbol);
console.log(symbol2);





При создании символов мы увидели одинаковые сообщения. но при этом символы не равны!

Каждый символ уникален. Это можно представить так. что внутри символа хранится некий уникальный код.

Таким образом имя символа мы используем для обращения к нему.

Создать два одинаковых символа нельзя!

Посмотреть на внутренние значения символа нам тоже не удастся.

Еще одним методом создания символов является метод Symbol.for.


let symbol = Symbol.for('name');

console.log(symbol);



В консоли получим тоже сообщение. что и при первом методе создания символа.



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


let symbol = Symbol.for('name');
let symbol2 = Symbol.for('name');

console.log(symbol === symbol2);



В консоли получим значение: true.

Первый и второй символы - это один и тот же символ.

Когда мы используем метод for, то он вначале попробует найти символ по имени и если ему это не удастся, то он создаст новый символ.

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

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

Имя символа можно получить методом keyFor.


let symbol = Symbol.for('name');
let name = Symbol.keyFor(symbol);

console.log(name);




В консоли мы увидим - name.

Если в метод .for не передать имя, то получим ошибку

let symbol = Symbol.for();

Будет ошибка!

Использование символов.

В ES5 свойства объектов должны быть строками.

В ES6 они могут быть строками и символами.

Создадим объекта и в качестве второго свойства присвоим символ.


let user = {
 name : 'John',
 [Symbol('password')] : 'r89n123'
};

console.log(user.password);



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

В консоли мы увидим undefined.

Попробуем посмотреть на все свойства объекта -


let user = {
 name : 'John',
 [Symbol('password')] : 'r89n123'
};

console.log(user.password);

console.log(Object.keys(user));



Мы увидим только name.



Попробуем еще и

console.log(Object.getOwnPropertyNames(user));



Как же получить доступ к паролю?

Давайте попробуем использовать метод .for().


let user = {
 name : 'John',
 [Symbol('password')] : 'r89n123'
};

console.log(user.password);

console.log(Object.keys(user));

console.log(Object.getOwnPropertyNames(user));

let password = user[Symbol.for('password')];

console.log(password);



И в консоли опять - undefined.



Если мы создаем символ с помощью функции Symbol(), то он не попадает в глобальный реестр и мы не сможем его найти с помощью метода .for()


выше приведено доказательство этому.

Но если у объекта указать с .for()


let user = {
 name : 'John',
 [Symbol.for('password')] : 'r89n123'
};

console.log(user.password);

console.log(Object.keys(user));

console.log(Object.getOwnPropertyNames(user));

let password = user[Symbol.for('password')];

console.log(password);





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

Этот метод находится у объектов Object и называется getOwnPropertySymbols


let user = {
 name : 'John',
 [Symbol.for('password')] : 'r89n123'
};

console.log(user.password);

console.log(Object.keys(user));

console.log(Object.getOwnPropertyNames(user));

let password = user[Symbol.for('password')];

console.log(password);

console.log(Object.getOwnPropertySymbols(user));





Даже если мы уберем .for у объекта, то все равно мы увидим тоже самое сообщение.



А если убрать и имя, то


let user = {
 name : 'John',
 [Symbol()] : 'r89n123'
};

console.log(user.password);

console.log(Object.keys(user));

console.log(Object.getOwnPropertyNames(user));

let password = user[Symbol.for('password')];

console.log(password);

console.log(Object.getOwnPropertySymbols(user));



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



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


let password = Symbol();

let user = {
 name : 'John',
 [password] : 'r89n123'
};

console.log(user.password);

console.log(Object.keys(user));

console.log(Object.getOwnPropertyNames(user));

// let password = user[Symbol.for('password')];

// console.log(password);

console.log(Object.getOwnPropertySymbols(user));





Результат будет тот же, но теперь символ хранится в переменной.

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

Так мы можем добавить нашему объекту еще одно свойство password.


let password = Symbol();

let user = {
 name : 'John',
 [password] : 'r89n123',
 password: 'a9b9c9n123'
};

console.log(user.password);

console.log(Object.keys(user));

console.log(Object.getOwnPropertyNames(user));

// let password = user[Symbol.for('password')];

// console.log(password);

console.log(Object.getOwnPropertySymbols(user));



В консоли:



При этом прямого доступа к символу нет, но это не значит, что его нет вообще.

При желании мы можем его получить.

Как я и говорил, нам как пользователям языка, нет необходимости создавать свои собственные символы, но в ES6 есть множество встроенных символов.

Эти символы называют - Well-known symbols или хорошо известные символы.

Одним из них является Symbol.iterator. Благодаря этому символу мы можем получить доступ к внутреннему методу объекта.

Выглядит это так:

У объекта должно быть свойство Symbol.iterator. Это свойство является методом, поэтому - круглые скобки и фигурные скобки .

Теперь мы можем добавить объекту свойство iterator и никакого конфликта не будет.


let object = {
 iterator: 0,
 [Symbol.iterator](){}
}



Этот метод, который мы определили, используется конструкцией forof благодаря которой мы можем перебирать или итерировать (отсюда и название символа) объект, у которого определен этот специальный метод.

Об этом мы поговорим уже в следующем посте.





                                                                                                                                                             

Комментариев нет:

Отправить комментарий



Хотите освоить самые современные методы написания React приложений? Надоели простые проекты? Нужны курсы, книги, руководства, индивидуальные занятия по React и не только? Хотите стать разработчиком полного цикла, освоить стек MERN, или вы только начинаете свой путь в программировании, и не знаете с чего начать, то пишите через форму связи, подписывайтесь на мой канал в Телеге, вступайте в группу на Facebook.Пишите мне - kolesnikovy70 почта gmail.com