Что добавят в JavaScript уже в 2020 году

Автор оригинала: Daniel Afonso
  • Перевод

Недавно опциональный доступ к аттрибутам (Optional Chaining) и значение по умолчанию для атрибутов (Nullish Coalescing) перешли на последний, четвёртый этап процесса TC39.


На практике это означает, что эти и другие нововведения станут частью стандарта JavaScript уже в этом, 2020 году. Их мы и рассмотрим в этой статье.


Отслеживать поддержку браузерами можно здесь («2020 features») — прим. перев.



String.prototype.matchAll


Использование «липких» (sticky) или глобальных регулярных выражений, когда надо захватить несколько групп на одной строке, может оказаться нетривиальным.


String.prototype.match не возвращает захваченные группы при наличии глобального флага, а без него можно получить только первое полное соответствие шаблону и его группы.


Пример:


let regexp = /t(e)(st(\d?))/g;
let str = 'test1test2';
const results = str.match(regexp);
console.log(results);

Результат с флагом «g»


Результат без флага «g»


Использование String.prototype.matchAll гарантирует, что будут возвращены все соответствия и их группы.


Пример:


let regexp = /t(e)(st(\d?))/g;
let str = 'test1test2';
let array = [...str.matchAll(regexp)];
console.log(array);

Результат:



BigInt


До появления BigInt наибольшее значение, представляемое Number, было равно 2⁵³-1 (MAX_SAFE_INTEGER). Теперь в JavaScript будет примитив, способный превзойти лимит.


Создать BigInt можно добавив 'n' к числу или используя функцию BigInt().


Пример:


let bigInt = 4n
console.log(bigInt * bigInt)

  • BigInt не эквивалентен Number, но может быть приведён к последнему.
  • При выполнении операций вроде деления, результат будет округлён до целого.
  • Нельзя использовать с Number без приведения типов.

Попытка сложить BigInt с числом...


let bigInt = 4n + 2
console.log(bigInt)

… приводит к исключению:



globalThis


Доступ к глобальным объектам в мире JavaScript всегда был головной болью. Вы должны быть знакомы со специфическим синтаксисом для окружения, что создаёт лишние трудности при написании переносимого кода и приводит к необходимости использовать что-то вроде getGlobal.


Пример:


var getGlobal = function () { 
  if (typeof self !== 'undefined') { return self; } 
  if (typeof window !== 'undefined') { return window; } 
  if (typeof global !== 'undefined') { return global; } 
  throw new Error('no global object found'); 
}; 

var globals = getGlobal(); 

С появлением globalThis можно перестать думать об окружении и получать глобальные объекты унифицировано.


Пример:


globalThis.someFunction = () => 'hello'

console.log(globalThis.someFunction())

Promise.allSettled


Допустим, у вас есть несколько промисов, и вы хотите что-то сделать после их завершения (неважно, успешного или нет). Promise.allSettled нужен именно для этого.


Пример:


const fulfilledPromise = Promise.resolve("success");
const rejectedPromise = Promise.reject("error")
const promises = [fulfilledPromise, rejectedPromise];

Promise.allSettled(promises).
  then((results) => results.forEach((result) => console.log(result)));

Результат:



Dynamic Import


Хотите загрузить модуль во время выполнения, в зависимости от определенного условия? Теперь это можно будет сделать без сторонних библиотек.


Достаточно вызвать функцию import, которая вернёт промис.


Пример:


import("some_module")
  .then(module => {
    module.doSomething();
  })
  .catch(err => {
    console.error(err.message);
  });

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


Пример с использованием шаблона:


import(`${some_module}.js`)
  .then(module => {
    module.doSomething();
  })
  .catch(err => {
    console.error(err.message);
  });

Nullish coalescing


Когда нужно получить атрибут или значение по умолчанию, если он null или undefined, мы обычно используем оператор ‘||’.


До Nullish coalescing:


const response = someResponse.properties.mayBeUndefined || 'Response';

Представьте, однако, что атрибут имеет «ложное» значение.


Проблема использования ‘||’:


const someResponse = {properties: { mayBeUndefined: ''}}
const response = someResponse.properties.mayBeUndefined || 'Response';

console.log(response)

Результат:


Это нежелательное поведение. В данном случае нам нужно было значение атрибута, а не значение по умолчанию.

С Nullish coalescing этой проблемы не будет. Значение по умолчанию будет возвращено только для атрибутов null или undefined.


Использование Nullish coalescing:


const someResponse = {properties: { mayBeUndefined: ''}}
const response = someResponse.properties.mayBeUndefined ?? 'Response';

console.log(response)

Результат:


Optional Chaining


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


До Optional Chaining:


const someObj = {
  property: 'prop',
  otherProperty: {
    name: 'prop2'
  }
};

const property = someObj.NotOtherProperty ? someObj.NotOtherProperty.name: undefined;
console.log(property);

С появлением Optional Chaining, можно будет использовать оператор ‘?.’ для опционального доступа к под-атрибутам. Код ниже эквивалентен коду выше.


Использование Optional Chaining:


const someObj = {
  property: 'prop',
  otherProperty: {
    name: 'prop2'
  }
};

const property = someObj.NotOtherProperty?.name;
console.log(property);

Optional Chaining делает код гораздо чище, особенно, если атрибутов в строке много.


Заключение


Вы можете попробовать запустить примеры из статьи в консоли: некоторые из них уже реализованы в последних версиях браузеров, другие, вероятно, будут внедрены очень скоро. Так или иначе, к возможностям из статьи уже можно начинать относиться как к части языка образца 2020 года.

Реклама
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее

Комментарии 24

    0
    nullish coalescing — в тайпскрипте уже есть:

    let o: any = {id: 1, name: "odin"}
    console.log(o.name1 ?? o.name)

    Хм, в JS тоже сработало
      0
      до финальной стадии стандарта эти фичи ещё не дошли, но браузеры их уже поддерживают, это нормально
        0
        Да есть. Просто автор некорректно написал заголовок статьи и по этой причине всё пошло по пи@#е не так как было задумано.
        Статья о том, что включат в стандарт. То есть сейчас это работает, находится в стадии предложения внесения в стандарт, но может быть либо отклонено, изменено перед внесением и, наконец, внесено в стандарт.
          +2
          > но может быть либо отклонено, изменено перед внесением и, наконец, внесено в стандарт

          Боюсь, вы не правы. Это 4 этап TC39. Это означает, что ничего менять или отклонять уже не будут.
            +1
            Да, я тоже не пейсатель, поэтому затронул весь этот период от Stage 0 до внесения в стандарт и не сказал об этом :)
          0
          nullish coalescing — в тайпскрипте уже есть

          Как и Optional Chaining. А все остальное можно полифилами добить.

            –1
            А ещё в ts есть +, -, = и много всего другого из javascript!
            Вы в курсе что ts это js superset?
              –1

              Всё-равно нужно как-то завезти поддержку синтаксиса и семантики в компилятор TS.

              0

              Насколько я понял, TS начинает активную поддержку новых proposal, начиная с их перехода на stage 3, т.е. незадолго до включения в стандарт.

              +11
              Хоть мне и не лень написать код без Optional Chaining, но эта фича меня всегда радовала в других языках :) Радует как JS развивается в последние года.
                +7
                > Optional Chaining

                Я джвадцать джва года ждал эту фичу!
                  +8
                  Я джвадцать джва года ждал эту
                  Uncaught TypeError: Cannot read property 'feature' of undefined

                  +6
                  Ещё несколько лет, и JS превратится в удобный язык :)
                    +1
                    Последние два пункта да, постоянная головная боль. Ждём-ждём!
                      +1
                      > Попытка сложить BigInt с числом 4n + 2 приводит к исключению.
                      Удивляет, что от первоначальной философии языка отошли.
                      Впрочем, это хорошо и удобно для всех, кроме участников www.dwitter.net.
                        +1

                        Вообще это правильно что прекратили порочную практику сложения тёплого с мягким.

                          0
                          да, чёт странно, можно скаладывать всё что угодно, кроме BigInt, это явно не javascript
                          +1

                          А в NodeJS удобно использовать этот сайт — https://node.green/


                          Как только LTS версия ноды делает шаг вперёд — самое время проверять чего добавили и изучать если что было пропущено.


                          BigInt уже там давно и лично продакшн код с ним писал, а вот например штуки с опциональным чейнингом посвежее.


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


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

                            0

                            В 13 версию уже видел pr с приватными свойствами, выглядит классно, хоть я и был против такого синтаксиса.

                            +4
                            Ура! Наконец-то на JS можно рассчитывать гос.долг США без переполнений
                              0
                              Сожалению Nullish Coalescing, Optional Chaining работают немного не так, как хочется.
                              Проверка идет только последнего элемента на (null, void 0), а не всей цепочки.
                                +1

                                В каких жизненных ситуациях вы хотели бы, чтобы одним оператором делалось более одного действия сразу? О_о

                                • НЛО прилетело и опубликовало эту надпись здесь
                                    0
                                    Optional Chaining проверят тот элемент, к которому применён, а не последний.

                                    In a deeply nested chain like a?.b?.c, why should I write?.. at each level? Should I not be able to write the operator only once for the whole chain?
                                    By design, we want the developer to be able to mark each place that they expect to be null/undefined, and only those. Indeed, we believe that an unexpected null/undefined value, being a symptom of a probable bug, should be reported as a TypeError rather than swept under the rug.

                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                  Самое читаемое