Моя серия заметок ES6 in Depth, состоящая из 24 записей, описывает большинство синтаксических изменений и нововведений в ES6. В этой публикации я подведу итог всего изложенного в предыдущих статьях, чтобы дать возможность посмотреть еще раз на всё вместе.

Содержание
Часть первая: здесь.
Символы
Итераторы
Генераторы
Промисы
Maps
WeakMaps
Sets
WeakSets
Прокси
Reflection
Строки и Unicode
Модули
Пора отдохнуть от маркированных списков! Я вас предупреждал, что лучше прочитать серию статей целиком. Кстати, вы уже попробовали konami code?

Содержание
- Введение
- Инструментарий
- Assignment Destructing
- Spread Operator и Rest Parameters
- Стрелочные функции
- Шаблонные строки
- Литералы объектов
- Классы
- Let и Const
- Символы
- Итераторы
- Генераторы
- Промисы
- Maps
- WeakMaps
- Sets
- WeakSets
- Прокси
- Reflection
- Number
- Math
- Array
- Object
- Строки и Unicode
- Модули
Часть первая: здесь.
Символы
- Новый примитивный тип данных в ES6.
- Можно создавать собственные символы:
var symbol = Symbol() - Можно добавить описание для нужд отладки
Symbol('ponyfoo') - Символы неизменяемы и уникальны:
Symbol(),Symbol(),Symbol('foo')иSymbol('foo')– все разные. - Тип символов –
symbol, так чтоtypeof Symbol() === 'symbol'. - Можно создавать глобальные символы при помощи
Symbol.for(key).
- Если символ с этим
keyсуществует, вызов его вернет. - Иначе будет создан новый символ с
keyв качестве описания. Symbol.keyFor(symbol)– это обратная функция, принимающаяsymbolи возвращающая егоkey.- Глобальные символы глобальны, насколько это возможно, то есть абсолютно. Для доступа к символам используется единый глобальный регистр:
- контекст
window; - контекст
eval; - контекст
<iframe> Symbol.for('foo') === iframe.contentWindow.Symbol.for('foo').
- Также есть «широко известные» символы:
- не в глобальном регистре, доступный через
Symbol[name],напримерSymbol.iterator; - глобальный, в смысле
Symbol.iterator === iframe.contentWindow.Symbol.iterator; - используемый спецификациями для определения протоколов, таких как iterable protocol через
Symbol.iterator; - они не являются «широко известными» в общепринятом смысле.
- Итерировать по свойствам символов можно, это сложно и абсолютно не приватно.
- Символы скрыты для всех reflection-методов, предшествующих ES6.
- Символы доступны через
Object.getOwnPropertySymbols. - Вы не будете через них спотыкаться, но обязательно их найдете при активном поиске.
- Прочитайте ES6 Symbols in Depth.
Итераторы
- Итератор и iterable protocol определяют способ, с помощью которого будет происходить итерация по любому объекту, не только массивоподобному или массиву.
- «Широко известные»
Symbolиспользуются для назначения итератора любому объекту. var foo = { [Symbol.iterator]: iterable}, илиfoo[Symbol.iterator] = iterable.iterableявляется методом, возвращающим объект итератора, у которого есть методnext.- Метод
nextвозвращает объект с двумя свойствами:value and done. - Свойство
valueуказывает на текущее значение в последовательности, по которой происходит итерация. - Свойство
doneуказывает на наличие оставшихся элементов для итерации. - Объекты, имеющие значение
[Symbol.iterator], доступны для итерации по ним, так как являются подписанными на iterable protocol. - Некоторые встроенные штуки вроде
Array,Stringилиarguments(иNodeListв браузерах) по умолчанию доступны для итерации в ES6. - Доступные для итерации объекты могут быть перебраны циклом
for..of, так же как иfor (let el of document.querySelectorAll('a')). - Доступные для итерации объекты могут быть созданы при помощи spread operator, например
[...document.querySelectorAll('a')]. - Также можно использовать
Array.from(document.querySelectorAll('a'))с целью создания массива из доступной для итерации последовательности. - Итераторы «ленивы», и те из них, которые создают бесконечный цикл, всё еще могут быть использованы в валидных программах.
- Будьте осторожны и не пытайтесь создать бесконечную последовательность при помощи… или
Array.from, потому что это приведет к созданию бесконечного цикла. - Прочитайте ES6 Iterators in Depth.
Генераторы
- Функции-генераторы – это особый вид итератора, который может быть объявлен при помощи синтаксиса
function* generator () {}. - Функции-генераторы используют ключевое слово
yield, чтобы возвращать элемент в последовательности. - Функции-генераторы также могут использовать
yield*для отсылки на другую функцию-генератор или любой доступный для итерации объект. - Функции-генераторы возвращают объект генератора, который придерживается протоколов итератора и iterable.
- Дано
g = generator(), gпридерживается iterable-протокола, потому чтоg[Symbol.iterator]является методом. - Дано
g = generator(), gпридерживается протокола итератора, потому чтоg.nextявляется методом. - Итератор для объекта генератора
g– это сам генератор:g[Symbol.iterator]() === g. - Можно получать значения при помощи
Array.from(g),[...g], for (let item of g) или просто вызвавg.next(). - Выполнение функции-генератора приостанавливается с запоминанием при этом последнего значения в четырех различных случаях:
- выражение
yieldвозвращает следующее значение в очереди; - выражение
returnвозвращает последнее значение в очереди; - выражение
throwполностью останавливает работу генератора; - достижение конца функции-генератора сигнализирует
{ done: true }. - Как только очередь
gзакончилась,g.next()просто возвращает{ done: true}, и больше ничего не происходит. - Очень просто писать асинхронный код в синхронном стиле.
- Используйте пользовательскую функцию-генератор.
- Пользовательский код останавливается на время выполнения асинхронных операций.
- Вызов
g.next()возобновляет выполнение пользовательского кода. - Прочитайте ES6 Generators in Depth.
Промисы
- Следуют спецификации Promises/A+, уже широко применяемой на практике задолго до того, как ES6 был стандартизирован (например bluebird).
- Промисы имеют древовидное поведение. Добавляйте ветви
p.then(handler)иp.catch(handler). - Создавайте новые промисы
pпри помощиnew Promise((resolve, reject) => { /* resolver */ }). - Callback
resolve(value)выполнит промис с указаннымvalue. - Callback
reject(reason)отклонит выполнение промиса с ошибкой reason. - Эти методы можно вызывать асинхронно, блокируя более глубокие ветви в дереве промисов.
- Каждый вызов
p.thenиp.catchсоздает еще один промис, который блокируется на время выполненияp. - Промисы создаются в состоянии ожидания и могут быть разрешены, будучи выполненными или отклоненными.
- Промис можно разрешить только один раз. Он становится разрешенным и разблокирует более глубоко вложенные ветви.
- Можно прикрепить сколько угодно промисов к любому необходимому количеству ветвей.
- Каждая ветвь выполнит свой обработчик .
thenили.catch, но никогда не выполняет оба обработчика. - Callback
.thenможет выполнить преобразование результата предыдущей ветви, вернув значение. - Callback
.thenможет блокировать другой промис, вернув его. p.catch(fn).catch(fn)не станет делать то, что вы хотите. Разве что вы хотите перехватывать ошибки в обработчике ошибок.Promise.resolve(value)создает промис, разрешенный с указаннымvalue.Promise.reject(reason)создает промис, отклоненный с указаннымreason.Promise.all(...promises)создает промис, который разрешается, когда все промисы...promisesвыполнены или один из них отклонен.Promise.race(...promises)создает промис, который разрешается, как только один из промисов...promisesбудет выполнен.- Используйте Promisees – песочницу для визуализации промисов, чтобы понять механизм их работы еще лучше.
- Прочитайте ES6 Promises in Depth.
Maps
- Замена распространенного паттерна создания hash-map при помощи простых объектов JavaScript.
- Помогает избежать проблем с безопасностью при работе с пользовательскими ключами.
- Можно использовать произвольные значения в качестве ключей, даже DOM-элементы или функции.
Mapпридерживается iterable-протокола.- Создавайте
mapпри помощиnew Map(). - Инициализируйте
mapпри помощиiterableвида[[key1, value1], [key2, value2]]в newMap(iterable). - Используйте
map.set(key, value)для добавления элементов. - Используйте
map.get(key)для получения элементов. - Проверяйте наличие
keyпри помощиmap.has(key). - Удаляйте элементы при помощи
map.delete(key). - Итерировать по
mapможно при помощиfor (let [key, value] of map), the spread operator,Array.from, и т. д. - Прочитайте ES6 Maps in Depth.
WeakMaps
- Похоже на
Map, но не то же. WeakMapне придерживается iterable протокола, так что у него нет таких методов перечисления, как.forEach,.clearи других, присутствующих вMap.- Ключи
WeakMapдолжны быть ссылками. Нельзя использовать данные типа symbol, number или string в качестве ключа. - Элементы
WeakMapсkey, являющимся единственной ссылкой на переменную, подбираются сборщиком мусора. - Из предыдущего пункта следует, что
WeakMap– отличный способ хранения метаданных об объектах, которые всё еще используются. - Вы избегаете утечек памяти без ручного учета ссылок – думайте о
WeakMapкак обIDisposableв .NET. - Прочитайте ES6 WeakMaps in Depth.
Sets
- Похоже на
Map, но не то же. - В
Setнет ключей, только значения. set.set(value)выглядит не очень, так что вместо него естьset.add(value).- В Set не может быть двух одинаковых значений, потому что значения Set – это его ключи.
- Прочитайте ES6 Sets in Depth.
WeakSets
- Нечто среднее между
SetиWeakMap. WeakSet– это set, по которому нельзя итерировать и у которого нет методов перечисления.- Ключи
WeakSetдолжны быть ссылками. WeakSetможет быть использован как таблица метаданных, показывающая, является ли ссылка активной.- Прочитайте ES6 WeakSets in Depth.
Прокси
- Создать прокси можно при помощи
new Proxy(target, handler), гдеtarget– это любой объект, аhandler– это настройки. - По умолчанию объект
proxyведет себя как ссылка на объектtarget. - Обработчики определяют способ осуществления доступа к объекту
targetпри помощи стандартной семантики доступа к свойствам объектов. - Вы передаете ссылки в
proxyи получаете полный контроль над способом общения сtarget. - Обработчики (handlers) также известны как ловушки (traps) – эти термины взаимозаменяемы.
- Вы можете создавать отзываемые прокси при помощи
Proxy.revocable(target, handler). - Этот метод вернет объект со свойствами
proxyиrevoke. - Для удобства можно писать так:
var {proxy, revoke} = Proxy.revocable(target, handler). - Можно настраивать
proxyточно так же, как и при помощиnew Proxy(target, handler). - После вызова
revoke() proxyбудет бросать исключение при любой операции, что очень удобно, когда вы не можете доверять пользователям вашего кода. get– ловитproxy.propиproxy['prop'].set– ловитproxy.prop = value и proxy['prop'] = value.has– ловит операторin.deleteProperty– ловит операторdelete operator.defineProperty– ловитObject.definePropertyи декларативные альтернативы.enumerate– ловит циклыfor..in.ownKeys– ловитObject.keysи подобные методы.apply– ловит вызовы функций.construct– ловит использование оператораnew.getPrototypeOf– ловит внутренние вызовы[[GetPrototypeOf]].setPrototypeOf– ловит вызовыObject.setPrototypeOf.isExtensible– ловит вызовыObject.isExtensible.preventExtensions– ловит вызовыObject.preventExtensions.getOwnPropertyDescriptor– ловит вызовыObject.getOwnPropertyDescriptor.- Прочитайте ES6 Proxies in Depth.
- Прочитайте ES6 Proxy Traps in Depth.
- Прочитайте More ES6 Proxy Traps in Depth.
Reflection
Reflection– новый статический встроенный элемент (вродеMath) в ES6.- Методы
Reflectionявляются чувствительными, например, Reflect.defineProperty возвращает boolean вместо того, чтобы бросить ошибку. - Существует метод Reflection для каждого обработчика прокси, он показывает поведение обработчика по умолчанию.
- Забегая наперед, можно сказать, что новые методы reflection будут заменены в пространстве имен Reflection в том же ключе, что и Object.keys.
- Прочитайте ES6 Reflection in Depth.
Number
- Используйте префикс
0bдля бинарных литералов и0o– для восьмеричных чисел. Number.isNaNиNumber.isFiniteработают так же, как и соответствующие глобальные методы, за исключением того, что не приводят вводные данные к типуNumber.Number.parseIntиNumber.parseFloatабсолютно идентичны соответствующим глобальным методам.Number.isIntegerпроверят соответствие вводных данных типуNumber– значение не должно иметь десятичной части.Number.EPSILONпомогает найти незначительные различия между двумя числами, например, между0.1 + 0.2и0.3.Number.MAX_SAFE_INTEGER– самое большое целое число, которое может быть безопасно и точно представлено в JavaScript.Number.MIN_SAFE_INTEGER– самое малое целое число, которое может быть безопасно и точно представлено в JavaScript.Number.isSafeIntegerпроверяет, может ли число быть представлено безопасно и точно.- Прочитайте ES6 Number Improvements in Depth.
Math
Math.sign– знак числа.Math.trunc– целая часть числа.Math.cbrt– кубический корень значения??value.Math.expm1– экспонента значения —1, или evalue – 1.Math.log1p– натуральный логарифм значения+ 1,илиln(value + 1).Math.log10– десятичный логарифм значения, или<sub>log10</sub> (value).Math.log2– двоичный логарифм значения, или<sub>log2</sub> (value)Math.sinh– гиперболический синус числа.Math.cosh– гиперболический косинус числа.Math.tanh– гиперболический тангенс числа.Math.asinh– гиперболический арксинус числа.Math.acosh– гиперболический арккосинус числа.Math.atanh– гиперболический арктангенс числа.Math.hypot– квадратный корень суммы квадратов.Math.clz32– количество ведущих нулевых битов в 32-битном представлении числа.Math.imul– C-like 32-битное умножение.Math.fround– округление числа до одного знака после запятой.- Прочитайте ES6 Math Additions in Depth.
Array
Array.from– создание экземпляра массива из массивоподобных объектов вродеargumentsили iterables.Array.of– похоже наnew Array(...items), но без частных случаев.Array.prototype.copyWithin– копирует последовательность элементов массива в другое место в этом же массиве.Array.prototype.fill– заполняет все элементы указанного массива переданным значением.Array.prototype.find– возвращает первое значение, удовлетворяющее условие.Array.prototype.findIndex– возвращает индекс первого значения, удовлетворяющего условие.Array.prototype.keys– возвращает итератор, который выдает последовательность, содержащую ключи массива.Array.prototype.values– возвращает итератор, который выдает последовательность, содержащую значения массива.Array.prototype.entries– возвращает итератор, который выдает последовательность, содержащую пары «ключ–значение» массива.Array.prototype[Symbol.iterator]– абсолютно то же, что и метод<a href="https://ponyfoo.com/articles/es6-array-extensions-in-depth#arrayprototypevalues">Array.prototype.values</a>.- Прочитайте ES6 Array Extensions in Depth.
Object
Object.assign– рекурсивная перезапись мелких свойств изtarget, ...objects.Object.is– похоже на использование оператора===, но также возвращаетtrueдля парNaN === NaNи+0 === -0.Object.getOwnPropertySymbols– возвращает все собственные символы объекта.Object.setPrototypeOf– изменяет прототип. Эквивалентен сеттеруtarget.__proto__.- Посмотрите также раздел «Литералы объектов».
- Прочитайте ES6
ObjectChanges in Depth.
Строки и Unicode
- Операции со строками:
String.prototype.startsWith– проверяет, что строка начинается со значения;String.prototype.endsWith– проверяет, что строка заканчивается значением;String.prototype.includes– проверяет, что строка содержит значение;String.prototype.repeat– возвращает строку, повторенную указанное количество раз;String.prototype[Symbol.iterator]– дает возможность итерировать по последовательности символов юникода (не самим символам).- Unicode
String.prototype.codePointAt– номер символа юникода в десятичной системе для элемента строки, указанного при помощи индекса;String.fromCodePoint– дано...codepoints, возвращает строку из соответствующих символов в unicode;String.prototype.normalize– возвращает нормализованную версию представления строки в unicode.- ?Прочитайте ES6 Strings and Unicode Additions in Depth.
Модули
- Строгий режим по умолчанию включен в модульной системе ES6.
- Модули ES6 – это файлы, экспортирующие API.
export default valueэкспортирует код по умолчанию.export var foo = 'bar'экспортирует именованный код.- Именованные экспорты – это связи, которые могут быть изменены в любое время из модуля, который их экспортирует.
export { foo, bar }экспортирует список именованных экспортов.export { foo as ponyfoo }дает возможность доступа к экспорту по псевдонимуponyfoo.export { foo as default }помечает именованный экспорт как экспорт по умолчанию.- Есть хороший способ избежать путаницы: писать в конце всех своих модулей
export default api, гдеapi– это объект. - Загрузка модулей зависит от имплементации, позволяет взаимодействовать с CommonJS.
import 'foo'загружает модульfooв текущий модуль.import foo from 'ponyfoo'присваивает локальной переменнойfooэкспорт по умолчаниюponyfoo.import {foo, bar} from 'baz'импортирует именованные экспортыfooиbarиз модуляbaz.import {foo as bar} from 'baz'импортирует именованный экспортfoo, но назначает псевдонимbar.import {default} from 'foo'также импортирует экспорт по умолчанию.import {default as bar} from 'foo'импортирует экспорт по умолчанию с псевдонимомbar.import foo, {bar, baz} from 'foo'смешивает экспорт по умолчаниюfooс именованными экспортамиbarиbazв одной инструкции.import * as foo from 'foo'импортирует объект пространства имён:- содержит все именованные экспорты в
foo[name]; - содержит экспорт по умолчанию в
foo.default, если таковой был объявлен в модуле. - Прочитайте ES6 Modules Additions in Depth.
Пора отдохнуть от маркированных списков! Я вас предупреждал, что лучше прочитать серию статей целиком. Кстати, вы уже попробовали konami code?
Комментарии (7)

baka_cirno
13.11.2015 13:15Минус в том, что половина этих фич сейчас нуждается в подключении дополнительных скриптов в рантайме. Простая трансляция в ES5 не прокатывает.

trikadin
13.11.2015 19:24+1Ну, полифиллы в нашем деле всегда были, есть и будут. На мой взгляд, полифилл — лучшее решение, чем слой абстракции для обеспечения одинаковой работы в разных браузерах с разными API.

some_x
13.11.2015 14:27> Вы избегаете утечек памяти без ручного учета ссылок – думайте о WeakMap как об IDisposable в .NET.
весьма натянутое сравнение на мой взгляд. Всё же в .NET есть намного более близкий аналог: WeakReference
ElianL
13.11.2015 16:32+1Promise.all(...promises) создает промис, который разрешается, когда все промисы ...promises выполнены или один из них отклонен.
Я конечно уверен всего лишь на 99%, но если хотя бы один из ..promises отклонен то Promise.all тоже будет отклонен
benjie
13.11.2015 16:54+2так и есть,
Промисы создаются в состоянии ожидания и могут быть разрешены, будучи выполненными или отклоненными.
igordata
> Maps
Аллилуйя!