JavaScript의 스펙을 정의하는 ECMAScript는 모던 자바스크립트의 시작점이라고 불리는 2015년 이후 매해 6월에 Stage 4 단계에 도달한 새로운 기능들을 공식적으로 업데이트한다.
2021년에 업데이트되는 새로운 기능 6가지
- String.prototype.replaceAll()
- Private Methods
- Promise.any
- Numeric separator
- Logical Assignment Operators
- WeakRefs and FinalizationRegistry
1. String.prototype.replaceAll()
replaceAll() 메소드는 어떠한 패턴과 일치하는 모든 값을 replacement와 교체한 새로운 string을 반환한다.
여기서 replacement는 string이나 함수가 될 수 있다. 본래의 string 값은 변하지 않는다.
// 1. String.prototype.replaceAll()
const string = "Annie, are you okay? So Annie are you okay? Are you okay?, Annie Annie, are you ok?";
console.log(string.replaceAll("Annie", "Jenny"));
// Jenny, are you okay? So Jenny are you okay? Are you okay?, Jenny Jenny, are you ok?
2. Private Methods
자바스크립트의 클래스 프로퍼티는 기본적으로 public이다. 즉 기본적으로 클래스 밖에서 읽을 수도 수정될 수도 있다. 이제는 hash (#) 접두사로 private 프로퍼티를 정의할 수 있다.
// 2. Private Methods
class Person {
showName() {
console.log("My name is Paul");
}
#showAge() {
console.log("I am 20 years old");
}
showAll() {
this.showName();
this.#showAge();
}
}
const person = new Person();
person.showName() // My name is Paul
person.showAge() // TypeError: person.showAge is not a function
persone.showAll() // My name is Paul, I am 20 years old
3. Promise.any()
Promise 들을 순회하면서 이 중 하나의 promise가 fulfilled 된 상태가 되면 이의 resolve 값을 반환한다. 만약 모든 Promise들이 fulfilled 되지 않고 reject가 되면 AggregateError를 반환한다.
// 3. Promise.any()
const p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("첫쨰"), Math.floor(Math.random() * 100));
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("둘째"), Math.floor(Math.random() * 100));
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => resolve("셋째"), Math.floor(Math.random() * 100));
})
try{
(async function() {
const result = await Promise.any([p1, p2, p3]);
console.log(result); // 첫째 || 둘째 || 셋쨰
})();
} catch (error) {
console.log(error); // AggregateError: All promises were rejected (셋다 reject 된다면)
}
Promise.any가 추가됨으로써 promise 세트를 다루는 비동기 연산들이 Promise.all, Promise.allSettled, Promise.race 에 이어 총 4개가 되었다. 이 중 Promise.any 는 Promise.race 와 비슷해 보이지만 분명 다른 점이 있다. 이러한 차이점을 알기 위해 먼저 fulfilled와 settled가 무엇인지 알아야 한다.
- fulfilled: promise가 이행된 상태
- rejected: promise가 어떠한 이유로 이행되지 못한 상태
- settled: fulfilled 되거나 rejected 된 상태
* Promise.race 는 여러 개의 promise들 중 가장 먼저 settled 된 promise를 반환한다.
* Promise.any는 여러개의 promise들 중 가장 먼저 fulfilled 된 promise를 반환한다. 하지만 fulfilled 없이 모두 rejected 된다면
AggregateError를 반환한다.
4. Numeric Separators
긴 숫자를 보다 정확하게 볼 수 있기 위해 underscore를 사용할 수 있다.
const pay = 10000000; // 백만? 첫만?
const payWith_ = 10_000_000;
console.log("pay", pay); // 10000000
console.log("pay", payWith_); // 10000000
console.log("pay", typeof(pay)) // Number
5. Logical Assignment Operators
수학적 연산자를 통해 x = x + y 는 x += y로 표현될 수 있다.
이제 && , || ,?? 의 논리 연산자를 사용하여 위와 같이 논리 할당을 할 수 있다.
let x = "파랑";
let y = "빨강";
let z;
x &&= y; // x 가 truthy 면 y로 바꾼다
console.log(x) // 빨강
x ||= y; // x 가 falsy 면 y로 바꾼다
console.log(y) // 파랑
z ??= x; // z 가 undefined 거나 null 이면 x로 바꾼다
console.log(z) // 파랑
6. WeakRefs and Finalizers
WeakRefs
WeakRef 객체는 다른 객체를 약하게 참조한다는 의미로 가비지 컬렉터의 대상이 되지 않는 기존의 강한 참조와는 다른 점이 특징이다.
약한 참조는 언제 실행될지 모르는 가비지 컬렉터가 객체의 메모리를 해제시키면 참조하는 곳에서 더 이상 해당 객체를 참조할 수 없게 된다.
const Obj = new WeakRef({
name: "Paul"
});
const callback = () => {
// WeakRef 인스턴스는 deref 메소드를 통해 두가지의 값 중 하나를 반환한다
// 1. constructor 에 전달된 객체
// 2. 객체의 값이 가비지 컬렉터에 의해 제거됬다면 undefined
console.log("deRef", Obj.deref().name); // "Paul" || undefiend
}
(async function(){
await new Promise((resolve) => {
setTimeout(() => {
callback(); // Paul
resolve();
}, 100);
});
await new Promise((resolve) => {
setTimeout(() => {
callback(); // Paul || undefiend
resolve();
}, 5000);
});
})();
// 브라우저와 자바스크립트의 엔진에 따라 가비지 컬렉터의 실행 시점이 다르기 때문에
// 언제 참조가 해제될지 예상하기는 힘들다.
TIP: 개발자 도구 → Performance에서 휴지통 아이콘을 누르면 강제로 가비지 컬렉터를 실행시킬 수 있다.

Finalizers
FinalizatiionRegistry constructor에 전달되는 콜백 함수는 register 메소드를 통해 등록한 객체가 가비지 컬렉터의 의해 메모리가 해제될 때 실행된다.
이 콜백 함수에는 register 메소드를 통해 등록한 객체의 사용을 피하고( 콜백 함수가 실행되는 시점에는 해당 객체가 메모리에서 해제되었기 때문에 참조할 수 없다 ) 별개의 값을 사용해야 한다.
class Person () {...};
const registry = new FinalizationRegistry((data) => {
console.log("message", data.message);
});
(function () {
const person = new Person();
registry.register(person, {message:"가비지 컬렉터에 의해 해제 됨"});
})();
가비지 컬렉터가 person 인스턴스의 메모리 영역을 해지 시 -> // 가비지 컬렉터에 의해 해제 됨
참고 링크:
Stage 4 새로운 기능들
tc39/proposals
Tracking ECMAScript Proposals. Contribute to tc39/proposals development by creating an account on GitHub.
github.com
https://thenewstack.io/ecmascript-2021-whats-next-for-javascript-webassembly/
ECMAScript 2021: What's Next for JavaScript? - The New Stack
The latest additions to JavaScript are mostly improvements to make working with the language more developer-friendly. And there's more: A powerful new option is designed to support WebAssembly.
thenewstack.io
https://backbencher.dev/javascript/es2021-new-features
ES2021 / ES12 New Features
Learn JavaScript, Node.js and NPM packages in depth
backbencher.dev
댓글