Продолжаем чтение статей Акселя Раушмайера (что поделать, они очень хороши). В этот раз попалась статья про оптимизацию хвостовых вызовов (tail call optimization - TCO) в ES2015.
Всё написано по делу и с хорошими примерами. Рассказывается про стек вызовов. Объясняется то, в каких случаях будет происходить оптимизация вызовов и в каких не будет, при этом даются советы про то, как это исправить. Например, некоторые рекурсивные функции без хвостовой оптимизации могут быть преобразованы в рекурсивную функцию с TCO, если воспользоваться дополнительной функцией-хелпером (как в примере с вычислением факториала).
Наличие оптимизации хвостовых вызовов помогает реализовывать рекурсивные алгоритмы более органично. Жаль только, что TCO, похоже, не скоро будет добавлен в v8 (Chromium) и SpiderMonkey (Firefox) из-за проблем с его реализацией. Поддержка TCO пока только есть в Safari.
#js #tco #fp #es2015
http://2ality.com/2015/06/tail-call-optimization.html
Всё написано по делу и с хорошими примерами. Рассказывается про стек вызовов. Объясняется то, в каких случаях будет происходить оптимизация вызовов и в каких не будет, при этом даются советы про то, как это исправить. Например, некоторые рекурсивные функции без хвостовой оптимизации могут быть преобразованы в рекурсивную функцию с TCO, если воспользоваться дополнительной функцией-хелпером (как в примере с вычислением факториала).
Наличие оптимизации хвостовых вызовов помогает реализовывать рекурсивные алгоритмы более органично. Жаль только, что TCO, похоже, не скоро будет добавлен в v8 (Chromium) и SpiderMonkey (Firefox) из-за проблем с его реализацией. Поддержка TCO пока только есть в Safari.
#js #tco #fp #es2015
http://2ality.com/2015/06/tail-call-optimization.html
Майлз Боринз три дня назад открыл пулл-реквест в Node.js с обновлённой имплементацией поддержки ES2015 Modules.
Самое значимое изменение – возможность использовать новые модули в файлах с расширением
1) используя расширение
2) используя расширение
3) используя расширение
Причиной изменения подхода стала критика со стороны сообщества предыдущего механизма, когда работа с ES модулями была доступна только в файлах
Разработчики Node.js пока не рекомендуют использовать ES модули в публикуемых пакетах. Релиз поддержки новых модулей без флага запланирован до выхода LTS версии Node.js 12 (октябрь 2019).
#nodejs #modules #esm #es2015
https://github.com/nodejs/node/pull/26745
Самое значимое изменение – возможность использовать новые модули в файлах с расширением
*.js. Теперь в Node.js есть три возможности работать с новыми модулями:1) используя расширение
*.mjs;2) используя расширение
*.js и type: module в package.json;3) используя расширение
*.js и флаги командной строки --type=module / -m.Причиной изменения подхода стала критика со стороны сообщества предыдущего механизма, когда работа с ES модулями была доступна только в файлах
*.mjs. Для сохранения совместимости с CommonJS было добавлено специальное расширение *.cjs.Разработчики Node.js пока не рекомендуют использовать ES модули в публикуемых пакетах. Релиз поддержки новых модулей без флага запланирован до выхода LTS версии Node.js 12 (октябрь 2019).
#nodejs #modules #esm #es2015
https://github.com/nodejs/node/pull/26745
GitHub
new ESM implementation by MylesBorins · Pull Request #26745 · nodejs/node
This PR updates the current --experimental-modules implementation based on the work of the modules team and reflects Phase 2 of our new modules plan.
A longer form description of these changes can ...
A longer form description of these changes can ...
Аксель Раушмайер у себя в блоге два дня назад опубликовал статью про то, как работают декларации в JavaScript — "Unpacking hoisting".
Аксель предлагает выделять следующие аспекты любых объявлений: область видимости (где к объявленной сущности можно обращаться) и активация (это черта динамична, она определяет, в какой момент исполнения кода можно обратиться к сущности).
Традиционные функции и var'ы всплывают и работа с ними не вызывает особых проблем. Особенности есть при работе с
Статья небольшая, но очень хорошая. Очень рекомендую почитать и поразбираться с примерами, если вы не знакомы с TDZ.
#js #es2015
http://2ality.com/2019/05/unpacking-hoisting.html
Аксель предлагает выделять следующие аспекты любых объявлений: область видимости (где к объявленной сущности можно обращаться) и активация (это черта динамична, она определяет, в какой момент исполнения кода можно обратиться к сущности).
Традиционные функции и var'ы всплывают и работа с ними не вызывает особых проблем. Особенности есть при работе с
const, let и class. Если обратиться к сущности в объявлении функции, то всё будет ок, но если попытаться выполнить эту функцию, когда сущность ещё не объявлена, то возникнет исключение ReferenceError. Промежуток времени между входом в область видимости сущности и исполнением инструкции с её объявлением называется Temporal Dead Zone (TDZ). Если в это время обратиться к объявляемым переменной/классу/функции, то возникнет исключение. Именно поэтому первый вызов функции из примера ниже выкинет исключение, а второй выполнится без ошибок:function a() {
return b;
}
a(); // throws ReferenceError
const b = 1;
a(); // 1Статья небольшая, но очень хорошая. Очень рекомендую почитать и поразбираться с примерами, если вы не знакомы с TDZ.
#js #es2015
http://2ality.com/2019/05/unpacking-hoisting.html
Proxy появился в ES2015, но до сих пор остаётся эзотерической фичей JavaScript. Про то чем он может быть полезен, рассказывает Томас Баррассо в статье "A practical guide to Javascript Proxy".
Proxy можно использовать для задания дефолтного значения, отличного от undefined, при обращении к несуществующему свойству объекта. С помощью него можно сделать python-like обращение к последнему элементу массива —
Это, конечно, не всё, на что способен Proxy. В статье упоминается, что он лежит в основе новой системы реактивности Vue 3. Ещё там есть ссылки на другие способы использования. В общем, статья хорошая, почитать стоит.
#es2015 #js
https://blog.bitsrc.io/a-practical-guide-to-es6-proxy-229079c3c2f0
Proxy можно использовать для задания дефолтного значения, отличного от undefined, при обращении к несуществующему свойству объекта. С помощью него можно сделать python-like обращение к последнему элементу массива —
arr[-1], скрытие свойств и инавалидирование свойств объекта, что может быть полезно при кешировании. Но больше всего мне понравился пример с перегрузкой оператора in, который позволяет реализовать проверку вхождения числа в заданный диапазон как в python 2 in range(1, 100) // true:const range = (min, max) => new Proxy(Object.create(null), {
has: (_, prop) => (+prop >= min && +prop <= max)
})Это, конечно, не всё, на что способен Proxy. В статье упоминается, что он лежит в основе новой системы реактивности Vue 3. Ещё там есть ссылки на другие способы использования. В общем, статья хорошая, почитать стоит.
#es2015 #js
https://blog.bitsrc.io/a-practical-guide-to-es6-proxy-229079c3c2f0
Medium
A practical guide to ES6 Proxy
Proxies on proxies for clean and composable Javascript metaprogramming
Аксель Раушмайер в прошлом месяце написал неплохую статью о том, как работают глобальные переменные в JS — "How do JavaScript’s global variables really work?"
Перед объяснением нюансов работы с глобальными переменными в статье рассказывается, что такое область видимости (scope) и как она определяется на уровне спецификации. В спеке области видимости "реализуются" с помощью lexical environments, которые состоят из environment record (нечто похожее на словарь с ключами и значениями) и ссылки на внешний scope. Таким образом дерево вложенных друг в друга областей видимости представляется деревом связанных между собой lexical environments.
На самом верхнем уровне этого дерева находится "global environment", состоящий из двух компонент: "object environment record", который поддерживает связь с свойствами глобального объекта (
Рекомендую почитать статью и посмотреть на примеры того, как это всё работает.
#specification #js #es2015
https://2ality.com/2019/07/global-scope.html
Перед объяснением нюансов работы с глобальными переменными в статье рассказывается, что такое область видимости (scope) и как она определяется на уровне спецификации. В спеке области видимости "реализуются" с помощью lexical environments, которые состоят из environment record (нечто похожее на словарь с ключами и значениями) и ссылки на внешний scope. Таким образом дерево вложенных друг в друга областей видимости представляется деревом связанных между собой lexical environments.
На самом верхнем уровне этого дерева находится "global environment", состоящий из двух компонент: "object environment record", который поддерживает связь с свойствами глобального объекта (
window / self в браузере и global в node.js), и "declarative environment record", который создаётся с помощью const, let, class. Эти части существуют независимо, что даёт возможность создавать биндинги с одинаковыми ключами в разных записях. При обращении к таким биндингам из кода будет побеждать declarative environment record. Если очень упростить, то можно сказать, что начиная со спецификации ES2015 в JavaScript появились два разных вида глобальных переменных.Рекомендую почитать статью и посмотреть на примеры того, как это всё работает.
#specification #js #es2015
https://2ality.com/2019/07/global-scope.html
Деструктуризация — удобное средство для доступа к свойствам объектов и элементам массивов, но оно не ограничивается только этими сценариями. Дмитрий Павлютин написал статью с описанием неочивидных подходов с использованием этой фичи — "5 Interesting Uses of JavaScript Destructuring".
1. С помощью деструктуризации можно обменивать значения переменных таким же образом, как это можно сделать в python:
2. Можно легко получить первый элемент массива с подстановкой дефолтного значения, если этого элемента нет:
3. Комбинируя деструктуризацию с rest-оператором, можно отбросить первый элемент массива:
4. Деструктуризация работает для всех объектов, которые имплементируют протокол итерирования (строки, массивы, Map, Set). Например, таким образом можно получить первую букву в строке:
5. Используя динамические свойства объектов, можно получить заранее неизвестное свойство объекта:
Я пересказал содержимое всей статьи, но всё равно в ней есть более развёрнутые примеры. Советую посмотреть.
https://dmitripavlutin.com/5-interesting-uses-javascript-destructuring/
#js #es2015 #list
1. С помощью деструктуризации можно обменивать значения переменных таким же образом, как это можно сделать в python:
[a, b] = [b, a];.2. Можно легко получить первый элемент массива с подстановкой дефолтного значения, если этого элемента нет:
const [firstColor = 'white'] = colors;.3. Комбинируя деструктуризацию с rest-оператором, можно отбросить первый элемент массива:
const [, ...lastNumbers] = numbers;.4. Деструктуризация работает для всех объектов, которые имплементируют протокол итерирования (строки, массивы, Map, Set). Например, таким образом можно получить первую букву в строке:
const [firstChar] = 'cheese';.5. Используя динамические свойства объектов, можно получить заранее неизвестное свойство объекта:
const { [nameProp]: name = 'Unknown' } = obj;.Я пересказал содержимое всей статьи, но всё равно в ней есть более развёрнутые примеры. Советую посмотреть.
https://dmitripavlutin.com/5-interesting-uses-javascript-destructuring/
#js #es2015 #list
Dmitri Pavlutin Blog
5 Interesting Uses of JavaScript Destructuring
A list of interesting and helpful applications of destructing assignments in JavaScript.
Валерий Карпов написал статью, посвящённую Symbol — "A Practical Guide to Symbols in JavaScript".
Symbol — это новый тип данных, который появился в ES2015. Символы могут использоваться в качестве ключа объекта. Они создаются с помощью функции
При создании символов с помощью
Статья небольшая, но хорошая. Рекомендую прочитать, если эта тема прошла мимо вас.
#js #es2015
http://thecodebarbarian.com/a-practical-guide-to-symbols-in-javascript.html
Symbol — это новый тип данных, который появился в ES2015. Символы могут использоваться в качестве ключа объекта. Они создаются с помощью функции
Symbol() и Symbol.for(), которые принимают на вход стоку-описание.При создании символов с помощью
Symbol() они гарантировано будут разными. Благодаря этой особенности можно отчётливо разграничивать пользовательские и программные данные. Например, в ES2015 символ Symbol.iterator используется для задания функции, которая будет вызываться при использовании for...of. При создании такого итератора его никто не сможет изменить по ошибке. При использовании Symbol.for('name') создаваемый символ сохраняется в глобальный реестр и становится доступен из разных мест программы при повторном вызове Symbol.for('name').Статья небольшая, но хорошая. Рекомендую прочитать, если эта тема прошла мимо вас.
#js #es2015
http://thecodebarbarian.com/a-practical-guide-to-symbols-in-javascript.html
The Code Barbarian
A Practical Guide to Symbols in JavaScript
Symbols, what are they good for? Here's some practical examples of what symbols are useful for in JavaScript.
Никогда такого не было и вот опять. Пару дней назад в твиттере выясняли, что лучше использовать
На этот раз этот всё началось с твита Дэна Абрамова, в котором он пошутил над участниками Reddit по поводу его недавней статьи, где он предлагал использовать
В итоге Дэн написал статью "On let vs const", где сравнил преимущества и недостатки использования eslint-правила
#history #es2015 #tc39
https://overreacted.io/on-let-vs-const/
https://twitter.com/littlecalculist/status/917875241891676160
https://twitter.com/awbjs/status/1208447372910444544
const или let.На этот раз этот всё началось с твита Дэна Абрамова, в котором он пошутил над участниками Reddit по поводу его недавней статьи, где он предлагал использовать
let. В треде он упомянул старый твит, в котором разработчики стандарта признают, что добавление двух способов для декларации переменных в блочном скоупе было ошибкой. Также в тред пришёл Аллен Вирфс-Брок — участник TC39, работавший над ES2015. Он написал, что const и let — наследие ES4, которому не придали большого внимания при переносе в ES2015. Аллен пишет, что если бы он мог это исправить, то оставил бы только const, но переименовал бы его в let. Затем в тред пришёл Брендан Айк и написал, что добавление const было вынужденной мерой, так как в некоторых движках он уже был имплементирован.В итоге Дэн написал статью "On let vs const", где сравнил преимущества и недостатки использования eslint-правила
prefer-const. Вывод простой — используйте то, что вам больше нравится.#history #es2015 #tc39
https://overreacted.io/on-let-vs-const/
https://twitter.com/littlecalculist/status/917875241891676160
https://twitter.com/awbjs/status/1208447372910444544
overreacted.io
On let vs const — overreacted
So which one should I use?
Стефан Баумгартнер написал пост про тип Symbol в JS и TypeScript — "Symbols in JavaScript and TypeScript".
Symbol используется для получения уникальных значений. С помощью символов можно разграничивать библиотечные и пользовательские данные в рамках одного объекта. Но это только одно их применение. В статье разбирается пример их использования для создания подобия enum в TypeScript, который кроме типобезопасности накладывает дополнительные ограничения в рантайме после компиляции в JavaScript:
Идея интересная, но в повседневном коде наврятли стоит использовать такой подход — обычный enum выглядит более эргономично.
#js #typescript #es2015
https://fettblog.eu/symbols-in-javascript-and-typescript/
Symbol используется для получения уникальных значений. С помощью символов можно разграничивать библиотечные и пользовательские данные в рамках одного объекта. Но это только одно их применение. В статье разбирается пример их использования для создания подобия enum в TypeScript, который кроме типобезопасности накладывает дополнительные ограничения в рантайме после компиляции в JavaScript:
const COLOR_RED: unique symbol = Symbol('RED')
const COLOR_GREEN: unique symbol = Symbol('GREEN')
const COLOR_BLUE: unique symbol = Symbol('BLUE')
const COLOR_BLACK: unique symbol = Symbol('BLACK')
const ColorEnum = {
[COLOR_RED]: COLOR_RED,
[COLOR_GREEN]: COLOR_GREEN,
[COLOR_BLUE]: COLOR_BLUE,
}
function getHexValueWithSymbolKeys(color: keyof typeof ColorEnum) {
switch(color) {
case ColorEnum[COLOR_BLUE]: break; // good
case COLOR_RED: break; // good
case COLOR_BLACK: break; // bad
}
}Идея интересная, но в повседневном коде наврятли стоит использовать такой подход — обычный enum выглядит более эргономично.
#js #typescript #es2015
https://fettblog.eu/symbols-in-javascript-and-typescript/
fettblog.eu
Symbols in JavaScript and TypeScript
symbol is a primitive data type in JavaScript and TypeScript, which, amongst other things, can be used for object properties. Compared to number and string, symbols have some unique features that make them stand out.