Pull to refresh

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

Reading time 4 min
Views 21K
Original author: 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 года.

Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+42
Comments 24
Comments Comments 24

Articles