IT-инфраструктура для бизнеса и творчества

JavaScript: десять новых фич в ES2020, о которых вам следует знать

Хорошие новости — новые фичи ES2020, улучшенной спецификации JavaScript, финализированы. Это означает, что теперь есть полное представление об изменениях, которые ждут нас в новом стандарте. Команда Mail.ru Cloud Solutions перевела и немного дополнила статью независимого фронтенд-разработчика со списком основных нововведений.

1. Biglnt

Появился тип данных BigInt — одно из самых ожидаемых нововведений в JavaScript. Он на деле позволяет разработчикам получить гораздо большее целочисленное представление в JS-коде для обработки данных.

На данный момент самое большое число, которое вы могли хранить в JavaScript в виде Integer, — это pow(2, 53) -1 (2 в 53 степени минус 1). Но BigInt позволяет выйти за эти пределы:

Однако вам нужно добавлять символ n в самом конце числа — это видно в примере выше. Символ n обозначает, что это данные в BigInt и должны быть иначе обработаны движком JavaScript (V8 или другим, который используется у вас).

Прим. переводчика: вы также можете создать переменную с новым типом BigInt через конструктор: BigInt(num).

Это улучшение не имеет обратной совместимости, так как традиционная система чисел подчиняется стандарту IEEE754 (который просто не поддерживает числа размера, допустимого в BigInt).

Прим. переводчика: также нужно внимательно отнестись к преобразованиям между Number и BigInt и к арифметическим операциям с последним, см. документацию.

2. Dynamic import

Опция динамического импорта — это функциональность из коробки, которая позволяет гибко подгружать JS-файлы как модули в вашем приложении. Это выглядит так же, как вы могли делать такую подгрузку раньше с помощью Webpack и Babel.

Это новшество поможет использовать прием доставки кода по требованию, более известный как code splitting (разделение кода), без всяких накладных расходов в виде модулей Webpack или других сборщиков кода. Вы также можете подгружать код в зависимости от условий в блоках if-else.

Хорошая вещь, так как вы фактически импортируете только сам модуль, и таким образом не загрязняете глобальное пространство имен:

3. Nullish Coalescing

Nullish coalescing добавляет возможность проверить null-подобные значения вместо проверки false-значений. В чем разница между null- и false-значениями, спросите вы?

В JavaScript многие значения false-подобные: это пустые строки, значение 0 в number, undefined, null, false, NaN.

Однако во многих ситуациях может потребоваться проверка, является ли выражение null-подобным, то есть равным только null или undefined. Например, когда вы допускаете, что переменная может быть пустой строкой, числом 0 или даже false.

В таком случае вы сможете использовать новый nullish coalescing-оператор ??:

Отлично видно, как оператор || всегда возвращает true-значение (не делает разницы между false, NaN, null, undefined), тогда как ?? возвращает не null значение (NaN и false).

4. Optional Chaining

Синтакс Optional Chaining позволяет обратиться к глубоко вложенным свойствам объекта, без того чтобы беспокоиться, есть ли такие свойства или нет.

Прим. переводчика: если точнее — позволяет обращаться к свойствам без проверки, существуют ли свойства объекта в цепочке свойств выше по иерархии.

Если они есть — отлично! Если нет, выражение вернет undefined.

Это работает не только со свойствами объектов, но также с вызовами функций и с массивами. Очень удобно! Вот примеры:

5. Promise.allSettled

Метод allSettled объекта Promise принимает массив промисов и разрешает их (resolve) только тогда, когда все они готовы — без разницы, в статусе resolved или rejected.

Раньше это не было доступно в нативном JS, хотя были похожие реализации, например, Promise.race или Promise.all. Это приносит в нативный JS подход «просто выполнить все промисы, результат выполнения каждого меня не интересует»:

6. String#matchAll

В прототип объекта String добавлен новый метод matchAll, который предназначен для работы с регулярными выражениями. Он возвращает итератор, который в свою очередь возвращает все подходящие группы в строке, одну за одной. Давайте посмотрим на простой пример:

7. globalThis

Если вы писали когда-нибудь кросс-платформенный JS-код, который должен работать в Node, в браузерном окружении, а также внутри web-workers, у вас наверняка были сложности с обращением к глобальному объекту.

Это происходит от того, что в браузере глобальный объект — это window, в среде исполнения Node.js — это global, в веб-воркерах — это self. Больше сред исполнения — больше различных значений глобального объекта.

Таким образом, вам потребуется ваша собственная имплементация функциональности по определению среды выполнения кода с последующим корректным использованием нужного глобального объекта — во всяком случае, так было до настоящего времени.

ES2020 подарил нам globalThis, который всегда указывает на текущий глобальный объект, независимо от того, в какой среде выполняется код:

8. Экспортирование пространств имен модулей

В модулях JavaScript всегда можно было использовать следующий import-синтакс:

import * as utils from './utils.mjs'

Однако до недавнего времени не было симметричного export-синтаксиса:

export * as utils from './utils.mjs'

До этого вы могли использовать эквивалент:

import * as utils from './utils.mjs' export { utils }

9. Четко описанный порядок перечисления в цикле for-in

Спецификация ECMA не указывала, в каком порядке должно выполняться перечисление свойств объекта в цикле for(x in y). Несмотря на то что браузеры до сих пор самостоятельно реализовали этот порядок, официально стандартизирован он был только в ES2020.

10. import.meta

Объект import.meta был создан в последней реализации ECMAScript, он имеет Prototype, равный null.

Рассмотрим подключаемый модуль:

<script type="module" src="module.js"></script>

Вы можете получить мета-данные этого модуля, используя объект import.meta:

console.log(import.meta); // { url: "file:///home/user/module.js" }

Он возвращает объект со свойством url, которое указывает на адрес модуля. Это может быть как адрес, по которому был загружен модуль (для внешних скриптов), так и document base URL (для инлайновых скриптов).

Прим. переводчика — также вы можете посмотреть неплохое видео по этой теме:

Впечатляет последовательность и скорость, с которой сообщество JavaScript эволюционировало и развивается. Удивительно и действительно замечательно наблюдать, как JavaScript прошел за десять лет путь от языка, который освистывали, к одному из сильнейших, гибких и универсальных языков.

Что еще почитать по теме:

{ "author_name": "Ekaterina Kushnir", "author_type": "self", "tags": [], "comments": 16, "likes": 24, "favorites": 47, "is_advertisement": false, "subsite_label": "dev", "id": 128188, "is_wide": true, "is_ugc": true, "date": "Tue, 19 May 2020 14:21:46 +0300", "is_special": false }
(function () { let cdnUrl = `https://specialsf378ef5-a.akamaihd.net/SelectelBranding/images/` let previousArticleNumber = null let currentArticleNumber = 0 let platform = 'Desktop' let articles = [ { name: 'camera', url: `${cdnUrl}CameraCat`, text: 'умную камеру для\u00A0наблюдения за\u00A0котиками', link: 'https://vc.ru/selectel/306690', num: 3 }, { name: 'chill', url: `${cdnUrl}ChillCat`, text: 'трекер, который подскажет, когда пора отдохнуть', link: 'https://vc.ru/promo/288561-eye-tracker', num: 1 }, { name: 'cloud', url: `${cdnUrl}CloudCat`, text: 'котика: даёшь ему «пять», а\u00A0он делает бэкап в облако', link: 'https://vc.ru/dev/294799-maneki-neko', num: 2 } ] let buttonCycle = document.querySelector('.button--cycle') let buttonChoose = document.querySelector('.button--choose') let buttonMobile = document.querySelector('.button--mobile') let textField = document.querySelector('.selectel-footer-subtitle') let imageAgent = document.querySelector('.image--agent') let banner = document.querySelector('.selectel-footer') buttonCycle.addEventListener('click', cycleClick) buttonChoose.addEventListener('click', () => sendEvent(`Promo ${articles[currentArticleNumber].num} Left`, 'Click')) buttonMobile.addEventListener('click', () => sendEvent(`Promo ${articles[currentArticleNumber].num} Left`, 'Click')) let media = window.matchMedia("(max-width: 570px)") media.addEventListener('change', matchMedia) function matchMedia() { if (media.matches) { platform = 'Mobile' } else { platform = 'Desktop' } update() } matchMedia() function cycleClick(event) { sendEvent(`Promo ${articles[currentArticleNumber].num} Right`, 'Click') if (event) { event.preventDefault() event.stopPropagation() } window.open('https://vc.ru/tag/selectelDIY', '_blank') //cycle(event) } function cycle(event) { // incrementArticleNumber() textField.innerHTML = generatedText() imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?3' imageAgent.setAttribute("class", "") imageAgent.classList.add('image--agent', articles[currentArticleNumber].name) banner.href = articles[currentArticleNumber].link } function update() { banner.href = articles[currentArticleNumber].link imageAgent.src = articles[currentArticleNumber].url + platform + '.svg' textField.innerHTML = generatedText() } function incrementArticleNumber() { previousArticleNumber = currentArticleNumber if (currentArticleNumber >= articles.length - 1) { currentArticleNumber = 0 } else { currentArticleNumber++ } } const sendEvent = (label, action = 'Click') => { const value = `SelectelDIY — loc: Footer — ${label} — ${action}`; if (window.dataLayer !== undefined) { window.dataLayer.push({ event: 'data_event', data_description: value, }); } }; function generatedText() { let defaultText if (platform === 'Desktop') { defaultText = `Мы тут собрали %text%. Хотите научим?` } else { defaultText = `Мы тут собрали %text%.` } return defaultText.replace('%text%', articles[currentArticleNumber].text) } function getRandom(min, max) { min = Math.ceil(min) max = Math.floor(max) return Math.floor(Math.random() * (max - min + 1)) + min } (function create() { currentArticleNumber = getRandom(0, articles.length - 1) cycle() let page = document.querySelector('.page--entry') if (page) { function insertAfter() { let parents = page.querySelectorAll('[data-id="7"]') let referenceNode = parents[0] referenceNode.parentNode.insertBefore(banner, referenceNode.nextSibling); loaded() } setTimeout(() => insertAfter(), 0) } }()) function loaded() { banner.classList.add('loaded') } loadImages([ `${cdnUrl}CameraCatDesktop.svg`, `${cdnUrl}ChillCatDesktop.svg`, `${cdnUrl}CloudCatDesktop.svg`, `${cdnUrl}CameraCatMobile.svg`, `${cdnUrl}ChillCatMobile.svg`, `${cdnUrl}CloudCatMobile.svg?3`, ]) function loadImages(urls) { return Promise.all(urls.map(function (url) { return new Promise(function (resolve) { var img = document.createElement('img'); img.onload = resolve; img.onerror = resolve; img.src = url; }); })); } }())
0
16 комментариев
Популярные
По порядку
Написать комментарий...

Наконец-то я могу читать Хабр без токсичных комментариев

15

Четко описанный порядок перечисления в цикле for-in

4

Спасибо, интересно. Optional Chaining очень не хватало, когда работаешь с необязательными параметрами. 

6

Typescript же ну 

1

Кхм-кхм, CoffeeScript

0

Даа, после использования Swift, эта фича прямо must have

1

Бигинт прям долго ждал, давно пора. Про код сплитинг - ну хз, это лишь малая часть задач вэбпака, так что у меня, например, отказаться не выйдет

4

Извините, а где вы используете бигинт?

0

один из примеров - работа с IPv6

1

Nullish Coalescing + Optional Chaining убирают сразу 9999 строк кода с проверками, ещё более читаемый js, ура🍻

4

Люто плюсую

0

Как же меня бомбит от этого огромного количества псевдоложных значений в JS.

2

Но менять это они никогда не будут

0

Очень интересно! Нихрена не понял!

1
Читать все 16 комментариев
Арт-экология. Уличные тренды и успешные городские проекты

Работы уличных художников, кроме эстетической роли, способны приносить пользу экологии за счет использования современных технологий. На стенах жилых домов уже появляются граффити с поглощающим смог эффектом, а на стволах деревьев – заживляющие рисунки.

Ленд-арт объект "Рогатка желаний" на фестивале ленд-арт в Муслюмово фото: организаторы фестиваля
В Ozon не хотят отменять заказ и возвращать деньги за недоставленный товар при доставке из-за рубежа
Retail Innovation Tech Alliance (RITA) дал старт новому отбору стартапов

Retail Innovation Tech Alliance (RITA) объявляет о шестом отборе стартапов для реализации совместных проектов с крупнейшими ритейл и технологическими корпорациями России и Казахстана.

Путин объявил «нерабочими» дни с 30 октября по 7 ноября с сохранением зарплаты Статьи редакции

Регионы могут сами установить сроки — начать уже с 23 октября.

М.Видео-Эльдорадо получила две награды престижной HR-премии «Хрустальная пирамида»
Microsoft выпустила веб-версию редактора кода VS Code Статьи редакции

Сервис работает без установки приложения или расширений для браузеров.

Делал дизайн, пока говорил по телефону: история Пола Рэнда, который создал логотипы для IBM и Стива Джобса Статьи редакции

Рисовал антифашистский журнал, работал арт-директором в Esquire и делал рекламу на азбуке Морзе.

Пол Рэнд   monitorbox
Lightshot дает доступ к снимкам всем подряд

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

Сделай сам: умная камера для наблюдения за питомцами

Обучаем нейросеть на котиках.

Sports.ru снял документальный фильм про «Зенит»-2008

В центре внимания — «золотое поколение» футбольного клуба, завоевавшее Кубок и Суперкубок УЕФА в 2008 году.

Трейлер фильма «Зенит-2008. Победная песня»
«Мегафон» заблокировал более 1000 корпоративных сим-карт

Наша организация предоставляет услуги мониторинга транспорта.

null