ECMAScript 2021

ECMAScript 2021 (ES12)에 추가된 일부 기능 정리

String.prototype.replaceAll()

문자열 혹은 정규식의 모든 항목을 문자로 바꾼다. String.prototype.replace()와 문법적으로는 동일하나 정규식의 /g플래그를 사용하지 않으면 첫번째 항목만 대체하는 replace()에 비해, replaceAll()은 모든 항목을 대체한다.

str.replaceAll(searchValue, replacementValue)

  • searchValue: 문자열, 정규식(정규식의 경우 /g 플래그를 넣어주지 않으면 TypeError가 발생한다.)

  • replacementValue: 문자열, 함수

"aabbcc".replace(/a/, "b"); // 'babbcc'
"aabbcc".replace(/a/g, "b"); // 'bbbbcc'

"aabbcc".replaceAll(/a/, "b"); // TypeError
"aabbcc".replaceAll(/a/g, "b"); // 'bbbbcc'

"6 / 4".replaceAll(/[0-9]+/g, (all) => 2 * Number(all)); // '12 / 8'

Promise.any()

Promise.any()는 프라미스 객체의 이터러블을 가지며, 이터러블(iterable) 프라미스 중 하나가 이행되면, 단일 프라미스를 이행된 프라미스 값과 함께 반환된다. Promise.any()signature는 아래와 같다.

Promise.any(promises: Iterable<Promise>): Promise

만약 모든 프라미스가 거부되면, 모든 거부 값이 그룹화되어 AggregateError로 새 하위 클래스와 함께 거부 된다.

class AggregateError { constructor(errors: Iterable, message: string); get errors(): Array; get message(): string; }

일부 이행시

const promise1 = Promise.reject("실패1");
const promise2 = new Promise((resolve) =>
  setTimeout(resolve, 100, "빠른 성공")
);
const promise3 = new Promise((resolve) =>
  setTimeout(resolve, 500, "느린 성공")
);

const promises = [promise1, promise2, promise3];

Promise.any(promises).then((value) => console.log(value)); // 빠른 성공

전체 거부시

const promise1 = Promise.reject("실패1");
const promise2 = Promise.reject("실패2");
const promise3 = Promise.reject("실패3");

const promises = [promise1, promise2, promise3];

Promise.any(promises).then((value) => console.log(value)); // AggregateError: All promises were rejected

Promise.all() vs Promise.any()

이 둘은 서로 상반되며, 서로 다른 것에 중점을 둔다.

  • Promise.all(): 모든 이행에 관심이 있으며, 하나의 거부라도 있으면 전체를 거부한다.

  • Promise.any(): 첫 번째 이행에만 관심이 있으며, 모든 거부에만 거부로 이어진다.

Promise.race() vs Promise.any()

이 둘의 관계도 살펴보자.

  • Promise.race(): 가장 빨리 확정된 프라미스(성공/실패)를 반환한다. -> '먼저 종료된 비동기 계산이 무엇이지?'

  • Promise.any(): 가장 먼저 이행된 프라미스(성공)을 반환한다. -> '먼저 성공한 비동기 계산이 무엇이지?'

// 위 코드와 동일
// ...
const promises = [promise1, promise2, promise3];

Promise.race(promises).then((value) => console.log(value)); // 실패1

Logical assignment operators

아래 논리 할당 연산자는 왜 사용하는 것일까라는 궁금증이 있어 찾아봤다.

이유는 예를들어 a = a || b로 사용했을 경우 항상 할당을 수행하지만, a ||= b로 사용했을 경우 필요한 경우에만 할당을 수행하기 때문이다.

할당 연산자(*)(동일한 식)만약 'a'가 아래 값일 경우에만 할당

a ||= b

a || (a = b)

Falsy

a &&= b

a && (a = b)

Truthy

a ??= b

a ?? (a = b)

Falsy

// case1
a = "";

a = a || "비";
a ||= "비";

// case2
a = "에이";

a = a || "비";
a ||= "비";

Underscores (_) as separators in number literals

긴 숫자 리터럴의 경우 숫자 사이에만 언더스코어(_)를 넣어 아래와 같이 입력할 수 있다.

const longNumber1 = 1_234_567; // 1234567
const longNumber2 = 10_000_000; // 10000000

const invalidCase1 = 1._101; // SyntaxError
const invalidCase2 = 1__101; // SyntaxError

주의해야할 점은 숫자 구문 분석을 위한 Number(), parseInt(), parseFloat() 함수에서는 구분 기호를 지원하지 않는다.

const longNumber1 = 1_234_567; // 1234567

Number(longNumber1); // 1234567
parseInt(longNumber1); // 1234567
parseFloat(longNumber1); // 1234567

// Warning
Number("1_234_567"); // NaN
parseInt("1_234_567"); // 1
parseFloat("101_234_567"); // 101

Last updated