Моя серия заметок ES6 in Depth, состоящая из 24 записей, описывает большинство синтаксических изменений и нововведений в ES6. В этой публикации я подведу итог всего изложенного в предыдущих статьях, чтобы дать возможность посмотреть еще раз на всё вместе. Также я добавил ссылки на мой блог, чтобы в случае необходимости сразу же можно было посмотреть подробнее.
Я слышал, вы любите маркированные списки, так что вот вам статья со списком, который состоит из нескольких сотен элементов.
Для начала приведу оглавление, чтобы было понятно, о чем пойдет речь. Очевидно, что оглавление – это также ненумерованный список. Обратите внимание: если хотите глубже вникнуть в эту тему, прочтите весь цикл статей и самостоятельно «поковыряйте» код ES6.
Содержание
? Введение
? Инструментарий
? Assignment Destructing
? Spread Operator и Rest Parameters
? Стрелочные функции
? Шаблонные строки
? Литералы объектов
? Классы
? Let и Const
? Символы
? Итераторы
? Генераторы
? Промайсы
? Maps
? WeakMaps
? Sets
? WeakSets
? Прокси
? Reflection
? Number
? Math
? Array
? Object
? Строки и Unicode
? Модули
Извините за такое длинное оглавление. Начинаем.
Введение
? ES6 (также известен как Harmony, es-next, ES2015) – последняя и окончательная спецификация языка.
? Окончательная спецификация ES6 была утверждена в июне 2015 года (следовательно, ES2015).
? Будущие версии языка будут называться согласно шаблону ES[YYYY], например ES2016 для ES7.
o Ежегодный релиз-цикл, необратимые изменения начинают действовать со следующего релиза.
o Так как ES6 появился раньше, чем это решение, большинство из нас всё еще называет его ES6.
o Начиная с ES2016 (ES7), мы должны использовать шаблон ES[YYYY], чтобы ссылаться на новые версии.
o Главная причина использования такого шаблона именования – оказание давления на производителей браузеров с целью как можно более быстрого внедрения последних обновлений.
Инструментарий
? Чтобы использовать ES6 сегодня, вам потребуется JavaScript-to-JavaScript транспайлер.
? Транспайлеры пришли и останутся, потому что:
o они предоставляют возможность компилировать код новой версии языка в код старой версии;
o мы будем транспайлить ES2016 и ES2017 в ES6 и т. д., когда браузерная поддержка станет лучше;
o нам потребуется улучшенный функционал source mapping;
o на сегодняшний день это самый надежный способ запускать ES6 код в продакшн (несмотря на то, что браузеры поддерживают ES5).
? У babel (транспайлера) есть киллер-фича: человекочитаемый вывод (human-readable output).
? Используйте babel, чтобы транспайлить ES6 в ES5 для статических сборок.
? Используйте babelify, чтобы внедрить babel в свой grunt, gulp или npm run процесс сборки.
? Используйте nodejs весии 4.x.x или выше – там есть весьма приличная поддержка ES6 (спасибо v8).
? Используйте babel-node с любой версией node.js – он будет транспайлить модули в ES5.
? В babel есть разрастающаяся экосистема, которая уже поддерживает ES2016 и некоторые плагины.
? Прочитайте A Brief History of ES6 Tooling.
Assignment Destructuring
? var {foo} = pony то же, что var foo = pony.foo.
? var {foo: baz} = pony то же, что var baz = pony.foo
? Можно задавать значения по умолчанию, var {foo='bar'} = baz вернет foo: 'bar', если baz.foo является undefined.
? Можно затащить сколько угодно свойств, под псевдонимами или без них:
o var {foo, bar: baz} = {foo: 0, bar: 1} даст foo: 0 и baz: 1.
? Можно пойти дальше: var {foo: {bar}} = { foo: { bar: 'baz' } } даст bar: 'baz'.
? Этому тоже можно назначить псевдоним: var {foo: {bar: deep}} = { foo: { bar: 'baz' } } даст вам deep: 'baz'.
? Свойства, которые не были найдены, по-прежнему возвращают undefined var {foo} = {}.
? Вложенные свойства, которые не были найдены, возвращают ошибку var {foo: {bar}} = {}.
? Это также работает для массивов, [a, b] = [0, 1] вернет a: 0 и b: 1.
? Можно пропускать элементы в массиве, [a,, b] = [0, 1, 2], получаем a: 0 и b: 2.
? Переменные можно менять местами, не прибегая к помощи третьей “aux” переменной, [a, b] = [b, a].
? Можно также использовать destructuring в параметрах функций:
o присваивание значений по умолчанию function foo (bar=2) {};
o эти значения могут также быть и объектами function foo (bar={ a: 1, b: 2 }) {};
o можно деструктурировать bar полностью: function foo ({ a=1, b=2 }) {};
o если ничего не было передано, по умолчанию получаем пустой массив: function foo ({ a=1, b=2 } = {}) {}.
Прочитайте ES6 JavaScript Destructuring in Depth.
Spread Operator и Rest Parameters
? Rest parameters – это как arguments, только лучше.
o сигнатура метода объявляется как function foo (...everything) {};
o everything – это массив со всеми параметрами, переданными в foo;
o можно присвоить имя нескольким параметрам перед ...everything, например: function foo (bar, ...rest) {};
o эти параметры будут исключены из ...rest;
o ...rest должен быть последним параметром в списке.
? Spread operator – это даже лучше, чем магия, он также обозначается при помощи … синтаксиса:
o отменяет необходимость apply при вызове методов, fn(...[1, 2, 3]) – то же, что fn(1, 2, 3);
o упрощенная конкатенация: [1, 2, ...[3, 4, 5], 6, 7];
o позволяет слепить массивоподобные элементы или коллекции в массивы [...document.querySelectorAll('img')];
o также полезен при destructing [a,, ...rest] = [1, 2, 3, 4, 5] возвращает a: 1 и rest: [3, 4, 5];
o делает new + .apply простым, new Date(...[2015, 31, 8]).
? Прочитайте ES6 Spread and Butter in Depth.
Стрелочные функции
? Лаконичный способ объявить функцию param => returnValue.
? Полезно при функциональном программировании, [1, 2].map(x => x * 2).
? Есть несколько разных способов использования (займет некоторое время, чтобы выработать привычку):
0 p1 => expr отлично подходит, если параметр один;
0 p1 => expr имеет неявный оператор return для выражения expr;
0 чтобы неявно вернуть объект, нужно обернуть его в круглые скобки () => ({ foo: 'bar' }), иначе получите ошибку;
0 круглые скобки необходимы, когда у вас 0, 2 или больше параметров () => expr or (p1, p2) => expr;
0 фигурные скобки в правой части представляют блок кода, в котором может содержаться несколько инструкций () => {};
0 при использовании такого синтаксиса неявного return нет, его нужно писать () => { return 'foo' }.
? Нельзя статически давать стрелочной функции имя, но тесты производительности намного лучше для большинства методов без имени.
? Стрелочные функции привязаны к лексическому окружению:
0 this это тот же контекст this, что и в родительском лексическом окружении;
0 this нельзя изменить при помощи .call, .apply, или похожих методов “reflection”-типа.
? Прочитайте ES6 Arrow Functions in Depth.
Шаблонные строки
? Строки можно объявлять при помощи обратных кавычек (`) в дополнение к одинарным и двойным.
? Строки с обратными кавычками являются шаблонными строками.
? Шаблонные строки могут быть многострочными.
? Шаблонные строки позволяют производить промежуточные вычисления `ponyfoo.com is ${rating}`, где rating – это переменная.
? Можно использовать любое валидное js-выражение для вычисления, например: `${2 * 3}` или `${foo()}`.
? Можно использовать помеченные шаблоны, чтобы изменить логику вычисления промежуточных значений:
0 добавить префикс fn к fn`foo, ${bar} and ${baz}`;
0 fn вызывается единожды с template, ...expressions;
0 template – это ['foo, ', ' and ', ''], а expressions – это [bar, baz];
0 результат fn становится значением шаблонной строки;
0 возможные примеры использования: очистка вводимых выражений от лишних данных, парсинг параметров и т. д.
? Шаблонные строки практически во всем лучше строк, обернутых в одинарные или двойные кавычки.
? Прочитайте ES6 Template Literals in Depth.
Литералы объектов
? Вместо { foo: foo }, можно писать просто { foo } – сокращенная форма записи пары свойство–значение.
? Вычисляемые имена свойств: { [prefix + 'Foo']: 'bar' }, где prefix: 'moz' возвращает { mozFoo: 'bar' }.
? Нельзя одновременно пытаться использовать две предыдущих особенности, запись {[foo]} – невалидна.
? Определения методов можно сделать более лаконичными при помощи следующего синтаксиса: { foo () {} }.
? Смотрите также секцию Object.
? Прочитайте ES6 Object Literal Features in Depth.
Классы
? Не «традиционные» классы, а синтаксический сахар поверх механизма наследования прототипов.
? Синтаксис похож на объявление объектов class Foo {}.
? Методы экземпляра new Foo().bar объявляются при помощи упрощенного синтаксиса литералов объекта class Foo { bar () {} }.
? Статические методы – Foo.isPonyFoo() – нуждаются в префиксе, ключевом слове static class Foo { staticisPonyFoo () {} }.
? Метод конструктора class Foo { constructor () { /* initialize instance */ }.
? Прототипное наследование с упрощенным синтаксисом class PonyFoo extends Foo {}.
? Прочитайте ES6 Classes in Depth.
Let и Const
? let и const – это альтернативы var при объявлении переменных.
? let имеет блочную область видимости, а не лексическую, по отношению к родительской функции.
? let поднимается в верхнюю часть блока, в то время как var поднимается в верхнюю часть функции.
? «Временная мертвая зона» или просто ВМЗ:
0 начинается в начале блока, в котором происходит объявление let foo;
0 заканчивается в том месте кода, где происходит объявление let foo (здесь «подъем» не имеет значения);
0 попытки доступа или определения foo внутри ВМЗ (до того, как будет выполнена инструкция let foo) приведут к ошибке;
0 помогает сократить число загадочных багов, в которых значение переменной претерпевает изменения раньше, чем происходит ее объявление.
? const также имеет блочную область видимости, «подъем» и следует семантике ВМЗ.
? Переменные const должны быть объявлены при помощи инициализатора const foo = 'bar'.
? Определение const после инициализации побуждает тихую ошибку (или не тихую – в строгом режиме).
? Переменные const не делают переменную неизменяемой:
0 const foo = { bar: 'baz' } значит, что foo всегда будет ссылаться на объект в правой части выражения;
0 const foo = { bar: 'baz' }; foo.bar = 'boo' не бросит исключение.
? Определение переменной с таким же именем – бросит.
? Предназначен для того, чтобы исправлять ошибки, когда вы переопределяете переменную и теряете ссылку на первоначальный объект.
? В ES6 функции имеют блочную область видимости:
0 предотвращают утечку данных через механизм «всплытия» { let _foo = 'secret', bar = () => _foo; };
0 не ломают пользовательский код в большинстве ситуаций и, как правило, являются тем, что вам нужно.
? Прочитайте ES6 Let, Const and the “Temporal Dead Zone” (TDZ) in Depth.
Я слышал, вы любите маркированные списки, так что вот вам статья со списком, который состоит из нескольких сотен элементов.
Для начала приведу оглавление, чтобы было понятно, о чем пойдет речь. Очевидно, что оглавление – это также ненумерованный список. Обратите внимание: если хотите глубже вникнуть в эту тему, прочтите весь цикл статей и самостоятельно «поковыряйте» код ES6.
Содержание
? Введение
? Инструментарий
? Assignment Destructing
? Spread Operator и Rest Parameters
? Стрелочные функции
? Шаблонные строки
? Литералы объектов
? Классы
? Let и Const
? Символы
? Итераторы
? Генераторы
? Промайсы
? Maps
? WeakMaps
? Sets
? WeakSets
? Прокси
? Reflection
? Number
? Math
? Array
? Object
? Строки и Unicode
? Модули
Извините за такое длинное оглавление. Начинаем.
Введение
? ES6 (также известен как Harmony, es-next, ES2015) – последняя и окончательная спецификация языка.
? Окончательная спецификация ES6 была утверждена в июне 2015 года (следовательно, ES2015).
? Будущие версии языка будут называться согласно шаблону ES[YYYY], например ES2016 для ES7.
o Ежегодный релиз-цикл, необратимые изменения начинают действовать со следующего релиза.
o Так как ES6 появился раньше, чем это решение, большинство из нас всё еще называет его ES6.
o Начиная с ES2016 (ES7), мы должны использовать шаблон ES[YYYY], чтобы ссылаться на новые версии.
o Главная причина использования такого шаблона именования – оказание давления на производителей браузеров с целью как можно более быстрого внедрения последних обновлений.
Инструментарий
? Чтобы использовать ES6 сегодня, вам потребуется JavaScript-to-JavaScript транспайлер.
? Транспайлеры пришли и останутся, потому что:
o они предоставляют возможность компилировать код новой версии языка в код старой версии;
o мы будем транспайлить ES2016 и ES2017 в ES6 и т. д., когда браузерная поддержка станет лучше;
o нам потребуется улучшенный функционал source mapping;
o на сегодняшний день это самый надежный способ запускать ES6 код в продакшн (несмотря на то, что браузеры поддерживают ES5).
? У babel (транспайлера) есть киллер-фича: человекочитаемый вывод (human-readable output).
? Используйте babel, чтобы транспайлить ES6 в ES5 для статических сборок.
? Используйте babelify, чтобы внедрить babel в свой grunt, gulp или npm run процесс сборки.
? Используйте nodejs весии 4.x.x или выше – там есть весьма приличная поддержка ES6 (спасибо v8).
? Используйте babel-node с любой версией node.js – он будет транспайлить модули в ES5.
? В babel есть разрастающаяся экосистема, которая уже поддерживает ES2016 и некоторые плагины.
? Прочитайте A Brief History of ES6 Tooling.
Assignment Destructuring
? var {foo} = pony то же, что var foo = pony.foo.
? var {foo: baz} = pony то же, что var baz = pony.foo
? Можно задавать значения по умолчанию, var {foo='bar'} = baz вернет foo: 'bar', если baz.foo является undefined.
? Можно затащить сколько угодно свойств, под псевдонимами или без них:
o var {foo, bar: baz} = {foo: 0, bar: 1} даст foo: 0 и baz: 1.
? Можно пойти дальше: var {foo: {bar}} = { foo: { bar: 'baz' } } даст bar: 'baz'.
? Этому тоже можно назначить псевдоним: var {foo: {bar: deep}} = { foo: { bar: 'baz' } } даст вам deep: 'baz'.
? Свойства, которые не были найдены, по-прежнему возвращают undefined var {foo} = {}.
? Вложенные свойства, которые не были найдены, возвращают ошибку var {foo: {bar}} = {}.
? Это также работает для массивов, [a, b] = [0, 1] вернет a: 0 и b: 1.
? Можно пропускать элементы в массиве, [a,, b] = [0, 1, 2], получаем a: 0 и b: 2.
? Переменные можно менять местами, не прибегая к помощи третьей “aux” переменной, [a, b] = [b, a].
? Можно также использовать destructuring в параметрах функций:
o присваивание значений по умолчанию function foo (bar=2) {};
o эти значения могут также быть и объектами function foo (bar={ a: 1, b: 2 }) {};
o можно деструктурировать bar полностью: function foo ({ a=1, b=2 }) {};
o если ничего не было передано, по умолчанию получаем пустой массив: function foo ({ a=1, b=2 } = {}) {}.
Прочитайте ES6 JavaScript Destructuring in Depth.
Spread Operator и Rest Parameters
? Rest parameters – это как arguments, только лучше.
o сигнатура метода объявляется как function foo (...everything) {};
o everything – это массив со всеми параметрами, переданными в foo;
o можно присвоить имя нескольким параметрам перед ...everything, например: function foo (bar, ...rest) {};
o эти параметры будут исключены из ...rest;
o ...rest должен быть последним параметром в списке.
? Spread operator – это даже лучше, чем магия, он также обозначается при помощи … синтаксиса:
o отменяет необходимость apply при вызове методов, fn(...[1, 2, 3]) – то же, что fn(1, 2, 3);
o упрощенная конкатенация: [1, 2, ...[3, 4, 5], 6, 7];
o позволяет слепить массивоподобные элементы или коллекции в массивы [...document.querySelectorAll('img')];
o также полезен при destructing [a,, ...rest] = [1, 2, 3, 4, 5] возвращает a: 1 и rest: [3, 4, 5];
o делает new + .apply простым, new Date(...[2015, 31, 8]).
? Прочитайте ES6 Spread and Butter in Depth.
Стрелочные функции
? Лаконичный способ объявить функцию param => returnValue.
? Полезно при функциональном программировании, [1, 2].map(x => x * 2).
? Есть несколько разных способов использования (займет некоторое время, чтобы выработать привычку):
0 p1 => expr отлично подходит, если параметр один;
0 p1 => expr имеет неявный оператор return для выражения expr;
0 чтобы неявно вернуть объект, нужно обернуть его в круглые скобки () => ({ foo: 'bar' }), иначе получите ошибку;
0 круглые скобки необходимы, когда у вас 0, 2 или больше параметров () => expr or (p1, p2) => expr;
0 фигурные скобки в правой части представляют блок кода, в котором может содержаться несколько инструкций () => {};
0 при использовании такого синтаксиса неявного return нет, его нужно писать () => { return 'foo' }.
? Нельзя статически давать стрелочной функции имя, но тесты производительности намного лучше для большинства методов без имени.
? Стрелочные функции привязаны к лексическому окружению:
0 this это тот же контекст this, что и в родительском лексическом окружении;
0 this нельзя изменить при помощи .call, .apply, или похожих методов “reflection”-типа.
? Прочитайте ES6 Arrow Functions in Depth.
Шаблонные строки
? Строки можно объявлять при помощи обратных кавычек (`) в дополнение к одинарным и двойным.
? Строки с обратными кавычками являются шаблонными строками.
? Шаблонные строки могут быть многострочными.
? Шаблонные строки позволяют производить промежуточные вычисления `ponyfoo.com is ${rating}`, где rating – это переменная.
? Можно использовать любое валидное js-выражение для вычисления, например: `${2 * 3}` или `${foo()}`.
? Можно использовать помеченные шаблоны, чтобы изменить логику вычисления промежуточных значений:
0 добавить префикс fn к fn`foo, ${bar} and ${baz}`;
0 fn вызывается единожды с template, ...expressions;
0 template – это ['foo, ', ' and ', ''], а expressions – это [bar, baz];
0 результат fn становится значением шаблонной строки;
0 возможные примеры использования: очистка вводимых выражений от лишних данных, парсинг параметров и т. д.
? Шаблонные строки практически во всем лучше строк, обернутых в одинарные или двойные кавычки.
? Прочитайте ES6 Template Literals in Depth.
Литералы объектов
? Вместо { foo: foo }, можно писать просто { foo } – сокращенная форма записи пары свойство–значение.
? Вычисляемые имена свойств: { [prefix + 'Foo']: 'bar' }, где prefix: 'moz' возвращает { mozFoo: 'bar' }.
? Нельзя одновременно пытаться использовать две предыдущих особенности, запись {[foo]} – невалидна.
? Определения методов можно сделать более лаконичными при помощи следующего синтаксиса: { foo () {} }.
? Смотрите также секцию Object.
? Прочитайте ES6 Object Literal Features in Depth.
Классы
? Не «традиционные» классы, а синтаксический сахар поверх механизма наследования прототипов.
? Синтаксис похож на объявление объектов class Foo {}.
? Методы экземпляра new Foo().bar объявляются при помощи упрощенного синтаксиса литералов объекта class Foo { bar () {} }.
? Статические методы – Foo.isPonyFoo() – нуждаются в префиксе, ключевом слове static class Foo { staticisPonyFoo () {} }.
? Метод конструктора class Foo { constructor () { /* initialize instance */ }.
? Прототипное наследование с упрощенным синтаксисом class PonyFoo extends Foo {}.
? Прочитайте ES6 Classes in Depth.
Let и Const
? let и const – это альтернативы var при объявлении переменных.
? let имеет блочную область видимости, а не лексическую, по отношению к родительской функции.
? let поднимается в верхнюю часть блока, в то время как var поднимается в верхнюю часть функции.
? «Временная мертвая зона» или просто ВМЗ:
0 начинается в начале блока, в котором происходит объявление let foo;
0 заканчивается в том месте кода, где происходит объявление let foo (здесь «подъем» не имеет значения);
0 попытки доступа или определения foo внутри ВМЗ (до того, как будет выполнена инструкция let foo) приведут к ошибке;
0 помогает сократить число загадочных багов, в которых значение переменной претерпевает изменения раньше, чем происходит ее объявление.
? const также имеет блочную область видимости, «подъем» и следует семантике ВМЗ.
? Переменные const должны быть объявлены при помощи инициализатора const foo = 'bar'.
? Определение const после инициализации побуждает тихую ошибку (или не тихую – в строгом режиме).
? Переменные const не делают переменную неизменяемой:
0 const foo = { bar: 'baz' } значит, что foo всегда будет ссылаться на объект в правой части выражения;
0 const foo = { bar: 'baz' }; foo.bar = 'boo' не бросит исключение.
? Определение переменной с таким же именем – бросит.
? Предназначен для того, чтобы исправлять ошибки, когда вы переопределяете переменную и теряете ссылку на первоначальный объект.
? В ES6 функции имеют блочную область видимости:
0 предотвращают утечку данных через механизм «всплытия» { let _foo = 'secret', bar = () => _foo; };
0 не ломают пользовательский код в большинстве ситуаций и, как правило, являются тем, что вам нужно.
? Прочитайте ES6 Let, Const and the “Temporal Dead Zone” (TDZ) in Depth.
dom1n1k
Я все-таки пока слабо понимаю, зачем сейчас нужен ES6 на фронте (с нодой вопросов нет) — ведь все равно приходится все конвертировать в 5 версию. Ну окей, какая-то часть нового функционала является просто синтаксическим сахарком и потому засовывается в режим совместимости безболезненно (например, стрелочные функции или let). Но вот классы и их наследование бабель конвертит в какие-то настолько жуткие и уродливые конструкции, что я лучше по старинке напишу.
Вот если бы можно было большинству клиентов подсовывать нативный es6 и только в старые браузеры отдавать бабель-версию, было бы понятно. А так все равно все будут жевать транс-компилированную версию.
Или я что-то не понимаю?
SerafimArts
Ну это как сравнивать паскаль и дельфи. В одном есть ООП, в другом его можно изобразить. Вроде даже похожие языки, но код в результате совершенно другой, не столько по синтаксису (и это тоже), сколько по стилистике.
Ну вот, для примера, небольшой набросок ActiveRecord на ES2015 (под клиент): https://gist.github.com/SerafimArts/cc85891cffb7c1fd235e
dom1n1k
Я понимаю, в чем достоинства ES6. Я не понимаю, как их сейчас по-нормальному использовать, если даже обладатели самых новых браузеров всё равно будут получать бабель-суррогат.
SerafimArts
А исходники зато чистые и красивые.
А как использовать нынче Go, Rust, C#, C++, etc, если даже обладателя самых новых процессоров будут получать ассемблер-суррогат? ;)
PerlPower
Мне думается, что компиляция языка высокого уровня в опкоды или байткод виртуальной машины это несколько другое нежели компиляция одного языка высокого уровня в другой язык высокого уровня.
И если уж вдаваться в детали, то программы на описанных вами языках пишутся для работы в одном, максимум 2-3 окружениях, это в конце концов не ANSI C. А сгенерированный ES5 будет работать минимум в 4 разных браузерах, которые еще и будут разных версий.
Кстати уважаемое JS-сообщество может дать мне ответ, почему оно в массе своей так радостно ждало ES6, который по факту работает в продакшене и будет работать еще минимум год исключительно через трансляторы, но все это время игнорировало clojurescript, coffescript, typescript — инструменты для которых воркфлоу один и тот же что и для текущего ES6?
rPman
Может потому что вероятность протащить 'clojurescript, coffescript, typescript — инструменты' в браузеры нативно намного меньше, чем поддержка ES6?
PerlPower
Но через год будет es2016, который опять таки будет поддерживаться только через трансляцию, а потом еще через год…
Понимаете, тут фундаментальная проблема в том, что в вебе ВСЕГДА будут старые броузеры. Поэтому единственный способ обеспечить работоспособность приложения у максимального числа пользователей — это транслировать в некую старую версию JS.
Так почему все проснулись только когда вышел es6, хотя по сути его использование ничем не отличается от того же coffeescript? Та же трансляция, та же отладка через сорц-мапы.
yatagarasu
Тут всетрчаются две мысли — зачем «самом модному хипстерскому сервису» поддержка каких-то там старых браузеров и зачему самому наджному древнему энтерпрайзу, все эти модные фишечки esXXXX.
Так что проблема я считаю надуманна, эти два множества никак не пересекаются.
Argutator
Таки лёд тронулся же. Тот же Microsoft отошел от именования версий браузеров — будет один Edge обновляемый подобно хрому. Использование старых версий в таком случае получается следованием принципу «сам себе злобный Буратино» — так можно и обновления безопасности, закрывающие дырки продуктов не ставить и потом страдать от того, что ими кто-то воспользовался.
SerafimArts
Я немного подумал и наконец понял в чём реально вопрос. Если я не угадал — просьба поправить.
Так вот, весь код на ES2015 (и даже ES2016) запросто переводится на ES5, включая даже некоторые API, вроде Map, Set и т.д., которые вроде как входят в спецификацию. Единственная проблема — это Proxy — единственное что невозможно транслировать и пока очень слабо поддерживается даже самыми современными браузерами. В остальном — абсолютно весь код можно запускать на любом браузере, используя все возможности современных версий даже на каких-нибудь относительно старых версиях браузеров (в пределах разумного конечно, не ИЕ6 какой-нибудь, хотя кто знает...).
Так что код бабела можно смело использовать в продакшене уже сейчас, а лет через 5 (надеюсь) можно будет тот же самый код отдавать уже без трансляции без каких-либо его исправлений.
bethrezen
Боюсь, что через 5 лет появится уже какой-нибудь ES2020, который вообще ни в одном месте не совместим ни с одним браузером. И опять всем придётся пользоваться babel или его аналогами.
Ну либо js браузерный всё же будет развиваться в другую сторону, нежели (io|node).js.
SerafimArts
Когда то было предложение (ссылку на статью на хабре я сейчас не найду) добавляющая в браузеры возможность передачи байткода, так что компилировать к 2020му году всё равно будет выгоднее, даже при условии, что браузеры будут поддерживать синтаксис этого ES2020. Ну это при условии, что браузеры начнут поддерживать этот байткод.
DarkPark
habrahabr.ru/post/261205
SerafimArts
P.S. А для создания читаемых классов можно использовать опцию loose es6.classes (в документации есть). Это сделает исходный код на выхлопе в разы читаемей (правда в результате не на 100% совместимый со стандартом). Хотя при наличии source maps читаемость результата и так не должна доставлять проблем.
TycoooN
Какая разница, что там получает браузер, если оно работает, как задумано? Вся соль в удобстве разработки.
dom1n1k
Я сейчас в песочнице просто из головы набрал
dark_ruby
вы когда на C#/Java/etc пишите, тоже потом скомпилированный байткод изучаете?
смысл использвания ES6 в том что вы получаете новые фишки языка, которые можете использовать сегодня! в том что вашь код становитсья коротким и понятным с первого взгляда, и.т.д.
zxcabs
Нормально все будет и 1000 строк и с 10 000 тысячами, код пишется в первую очередь для людей, поэтому то как он выглядит для машины не имеет ровным счетом никакого значения.
Во вторых, аргумент за производительность вообще не аргумент в этом контексте, я вам дам 100% гарантию что ваше приложение сначала начнет тормозить сначала из-за неправильной работы с дом, потом из за криворукости реализации, потом из за монстрячей конструкции какого нибудь фреймворка, примерно к концу списка тормоза можно будет объяснить вспышками на солнце, но и даже в этом случае тормоза из за кода трансплиттера будут еще далеко.
SerafimArts
Я уже написал выше — используйте loose mode, выхлоп сокращается до 50 с копейками строк, но не гарантируется 100% совместимость со стандартом (правда на практике никаких проблем с этим нет, если не влезать во внутренности реализации).
ankh1989
Если вы там нейросети на JS пишете (это про вашу неуверенность в быстроте), то лучше наверно использовать emscripten.
oWeRQ
Добавляется 70 строк общих фукций(если отформатировать), считай runtime, сами классы остаются довольно читабильными и не сильно жиреют. +6 строк в данном примере. Если убрать геттер и включить loose mode — код почти как рукописный, с прототипами и анонимными фукциями.
noder
А зачем пользователям отдавать исходные коды? Сейчас уже практически везде используют средства сборки/минификации скриптов и стилей. Использовать es6 для разработки на JavaScript повышает производительность и удобство разработки.
rPman
Попробуйте исследовать лицензии ваших любимых компонент, которые вы используете на javascript (или кстати любом другом скриптовом языке), и вы поймете, что либо вам придется отказываться от них, либо перелицензировать, либо принудительно открывать свои исходники, так как оно почти все GPL (правда часто LGPL или аналог).
p.s. кстати, а использование таких компиляторов из чегототам в javascript разве не освобождает программистов от необходимости выкладывать ИСХОДНЫЙ текст программы, если это требует лицензия на компоненты?
symbix
Гм. Использую десятки сторонних библиотек, везде MIT/BSD-лицензия.
PerlPower
Спасибо вам за перевод. Постарайтесь пожалуйста внимательнее относиться к опечаткам. И по возможности выделять код так же как и в оригинале. Но поскольку на хабре туго с форматированием, придется ограничиться <font color="#112233">.
? var {foo} = pony то же, что var foo = pony.foo.
Darina_PL
Спасибо, поправила опечатку. Когда буду заливать вторую часть, поправлю весь код по цвету.
klierik
Если честно, то перевод у вас, мягко сказать, не очень хороший. Вчера ребята из css-live запостили перевод этой статьи, вы извините, но по сравнению с вашим — земля и небо. Сравните сами.
menelion_elensule
Извините, по этому же поводу вопрос: а маркированные списки в оригинале тоже на самом деле не были HTML-списками? А то читать не очень удобно(
funca
На моей памяти, индустрия постоянно предпринимала попытки избавится от JS. Разработчики разных браузеров то и дело встраивали поддержку других языков, предлагая сообществу лучшие альтернативы. Но эта стратегия ни разу не принесла успеха. Подавляющее большинство продолжало упорно использовать JavaScript. Похоже, что на этот раз решили действовать по-другому, превратив JavaScript в Perl (как показала практика оно потом само дохнет).
Имхо, JS, несмотря на всю свою несуразность и изначальные просчеты, получил такое распространение и популярность благодаря простоте языка, четкому стандарту, не ломающейся годами совместимости и как следствие интероперабельности кода. Все это очень удобно на практике.
Теперь, наряду некоторым набором определенно полезных вещей, в спецификацию вбросили адову кучу синтаксических трюков, что усложняет язык в разы. Снаружи добавилось интсрументирование — трансплитеры уже необходимость. Если они собираются менять и спецификацию каждый год, то скоро эпохе JS придет конец.
rPman
Я вообще удивлен, что в браузерах до сих пор не установлена (и главное грамотно открыт доступ к компонентам) песочница с LLVM машиной, тогда разработчики могли бы работать с любым языком… да и с библиотеками, так хочется чтобы они в браузере ставились (загружались) не каждый раз при заходе, а устанавливались из репозитариев, желательно с cdn или с использованием p2p…
funca
Наверняка, о чем-то подобном мечтали и разработчики Sliverlite. Думаю здесь работает эффект «вавилонской башни» (я имею ввиду ту часть этой истории, когда люди говорили на одном языке, а потом их наказали). WEB основан на сравнительно небольшом множестве простых концепций, поддержанных в открытых стандартах. Мне кажется, что в таких масштабах профит от использования единого для всех языка перевешивает все недостатки (даже на сервер js притащили). Мультиязычность неплохо работает в огороженных мирках, но в массе, дробит сообщество и увеличивает хаос.
rPman
Именно Microsoft Silverlight был не способом исправить текущую ситуацию с языками, а способ затмить собой Adobe Flash со всеми вытекающими от сюда минусами от монополии.
LLVM полностью открыто, поддерживается сразу несколькими компаниями, УЖЕ имеет поддержку большого количества оборудования и вообще, я не понимаю, почему все на него не переходят дружными рядами.
Large
За исключением редких случаев которые не рекомендовались к использованию (типа блочного определения функций) будет полная обратная совместимость со старыми версиями. Можете продолжать писать хоть на ES3 и дальше. Введенные конструкции отчасти добавляют сахар для упрощения читаемости нового кода, отчасти призваны решить проблемы архитектуры больших приложений.
Zenitchik
Жаль, что переменная super определена только в классах. При программировании на прототипах она тоже была бы полезна.
Large
Да, это удобно, хотя тоже всего лишь сахар для обращения к родителю. Сейчас тоже ничто не мешает создать на него ссылку и записать ее в super.
Zenitchik
Конечно, можно. Каждый, кому не лень, писал свой велосипед.
Дело в том, что предложенный стандарт выглядит недоделанным. Скажем, переменная this существует всегда, можно заглянуть в спецификацию и узнать, чему она равна в каждом конкретном случае.
А вот super…
Large
Ну в строгом режиме к ней тоже нельзя обращаться всегда, так что ничего страшного — this как и super созданы для работы с классами где их и стоит применять.
Zenitchik
Проблема в том, что под капотом — prototype. С классами работать не всегда удобно. Класса у меня вообще может не быть, а super, тем не менее, нужен. Приходится в одном месте использовать нативный, а в другом — самоделку.
saggid
Большое спасибо за перевод полезного материала)
По теме ES2015 — немного понять для себя лично не могу до сих пор… Есть ли там действительно великие по полезности нововведения? Ну, появились let, const, ну, получили мы новые типы хешей. Синтаксический сахар — это вообще мелочь, хотя и приятно иногда с ним, но крайней необходимости в нём никогда не ощущал. Ну, «классы» теперь есть. Хотя я и раньше просто функцию создавал и запихивал в неё все нужные методы, мало чем от класса в итоге оно отличается.
Так есть ли там что-нибудь из реальных killer features? Может ли кто-нибудь пояснить?)
jMas
ИМХО, сделали вещи которые помогут чуть меньше наступать на грабли. Например, хотя бы объявление классов. Для людей из других ЯП код JS с новыми классами будет выглядеть привычней, да и мусора будет немного меньше. Некоторые штуки, пока с ними все не столкнутся — будут вызывать только недоумение, хотя на практике будут делать код короче (я сейчас о fn(...arr), это ведь действительно быстрее, чем fn.apply(this, arr)). Пока я увидел кучу синтаксического сахара, и трудно себе представляю код, который будет им изобиловать (сейчас я не о классах). Для меня он в читабельности несколько потеряет, пока я не освою все мельчайшие нюансы.
Интересно, а есть у разработчиков планы по решению бородатых неточностей JS?
SirEdvin
Ну, это выглядит как стандартизация костылей.
К тому же это странно, с одной стороны делать вход в язык для разработчиков проще, а с другой стороны добавлять такой адский синтаксический сахар как в разделах Assignment Destructuring и прочих.
Особенно { foo } выглядит совсем странно.
Zenitchik
Боюсь именно поэтому мусора станет больше, т.к. люди из других ЯП будут ещё реже заглядывать в спецификацию JS.
SerafimArts
Киллер фичи в основном в ES2016 есть, но так как мы все дружно пользуемся бабелом — разницы никакой. Сами фичи: async\await, проперти и декораторы
В ES2015 можно полукиллерфичами назвать как минимум import\export, классовые геттеры\сеттеры и генераторы + символ итератор метод.
Large
Так import/export пока нет так как Loader API не определили. Его скорей всего в 2016 добавят.
Large
Map, Set, Proxy, Reflect, Symbols, Promises, subclasses, generators, iterators, tail call optimisation — по моему достаточно киллер фич. Конечно в 2016 добавят намного больше, в том числе асинхронные функции которые помогут писать код в синхронном силе с помощью промисов. Но и 2015 — это большой шаг в нужную сторону (хотя я лично немного сомневаюсь на счет классов).
Large
Обидно, что
не работает и нужно его расписывать в 2 хода:
На самом деле не совсем понятно в чем разница при использовании между отсутствием всплытия и наличием ВМЗ. В реализации разница есть, но поведение как мне кажется от этого не меняется.
Определение функций внутри блока всегда было злом, но теперь удивительно, что область их видимости сузили до блока. Это хорошее решение, но оно потенциально может нарушить совместимость старого и нового кода.
В описаниях классов вообще противоречия:
при этом такую конструкцию приводят в пример как замену Foo.prototype.bar. Насколько мне известно — верно второе, да и babel записывает данные методы в прототип, а не в экземпляр.
Arilas
На самом деле работает первый пример, даже несколько… в одном массиве, вот пример:
Даже так можно
Large
На самом деле нет (можете проверить в ff). В вашем примере нет ни диструктивного присваивания ни переменных аргументов функции потому он и работает.
Nesvet
let не поднимается. Пруф:
SelenIT2
На той же mozilla.org есть и пруф, что поднимается:
И автор переведенной статьи отдельно подчеркивает это в ответе на первый же коммент (в котором, что интересно, тоже говорится о том, что «
let
(andconst
) hoist (with TDZ) to the top of the closest containing scope contour (block, function, or global)»!):Надеюсь, кто-нибудь из грамотных людей поможет рассудить…
rock
Ну можно сказать и поднимается, создавая TDZ, это скорее вопрос терминологии :)
rayz_razko
zxcabs
То что есть такая возможность не значит что в таком виде этим будут пользоваться везде и всюду.
По опыту могу сказать что такая запись
Читается вполне себе удобно и становится вполне привычной.
develop7
это же недоpattern matching, что здесь сложного?
raacer
o_O