ES2021 ~ 2022 정리

주형(Jureamer)·2022년 11월 18일
0

ECMA

목록 보기
3/3
post-custom-banner

ES2021

String.replaceAll()

기존에는 전역으로 string값을 수정하기 위해선 replace에 g(global) 옵션을 사용해야만 했는데
replaceAll로 간편하게 처리할 수 있게 되었다.

const 369Sentence = "12,45,78,"
console.log(369Sentence.replaceAll(",", "짝"); // 12짝45짝78짝

Promise.any()

Promise.any()는 iterable한 Promise들을 인자로 받아 첫 번째로 해결된 Promise가 생기면 바로 반환하는 메소드다. 모든 Promise가 reject 될 시에는 AggregateError가 발생한다.

const differentDepartureTime = [
    new Promise((res, rej) => setTimeout(res, 200, 'first')),
    new Promise((res, rej) => setTimeout(res, 300, 'second')),
    new Promise((res, rej) => setTimeout(res, 100, 'third')),
]

async function testPromise() {
    const result = await Promise.any(differentDepartureTime)
    console.log(result) // third
}
    
testPromise()


// 모두 reject로 가정 시
const differentDepartureTime = [
    new Promise((res, rej) => setTimeout(rej, 200, 'first')),
    new Promise((res, rej) => setTimeout(rej, 300, 'second')),
    new Promise((res, rej) => setTimeout(rej, 100, 'third')),
]

// 출력 [AggregateError: All promises were rejected] {[errors]: [ 'first', 'second','third' ]}

WeakRefs

기존에 자바스크립트 객체는 항상 강하게 참조가 되어서, 참고하고 있는 객체가 존재하고 있는 이상 객체가 가비지 컬렉팅 되지 않았다. 하지만 WeakRefs가 나오게 되면서 약한 참조가 가능하게 되었고 이를 이용하면 가비지 콜렉터가 수집(?)할 수 있는 대상이 되기에 시간이 지나면 메모리로 환원이 될 수 있다..! 하지만 이는 사용을 하더라도 굉장히 숙고하여 사용해야한고 가능한한 사용을 피하는 편이 좋다고 한다.
deref() 메소드는 WeakRefs 객체의 속성을 확인 할 수 있고 Finalizers라는 메소드를 통해 가비지 컬렉트가 되는 시점을 알 수 있어서 잘 조합하면 유용하게 사용할 수 있다.
이 부분에 대한 내용이 조금 많고 까다로워서 다음에 따로 포스팅하면 좋을 것 같다!

// 강한 참조
const map = new Map();

const obj =  {data: new Array(10).join('*')};

map.set('someData', obj);

setInterval(() => {
    console.log(map.get('someData').data);
}, 1000); 
// (Infinity) ********** 


// 약한 참조
const map = new Map();

const obj =  {data: new Array(10).join('*')};

map.set('someData', new WeakRef(obj));

setInterval(() => {
    console.log(map.get('someData').deref().data);
}, 1000); 
// (178) ********** 
// 환경마다 가비지 컬렉트 시간이 다를 수 있다.

Logical assignment operators (논리 할당 연산자)

세 가지의 논리 연산자가 추가 되었다. (&&=, ||=, ??=) 자주 쓰이는 +=와 같은 할당 연산자라고 보면 된다.

a &&= b // a = a && b
a ||= b // a = a || b
a ??= b // a = a ?? b

Numeric separators

큰 숫자의 가독성을 높일 수 있게 언더바(_)를 활용해 구분할 수 있게 되었다.
물론 언더바를 추가해도 연산이 가능하다

// 기존 
console.log(1000000000 + 1000000) // 몇 자리지..?

// 변경
console.log(1_000_000_000 + 1_000_000) // 10자리 + 7자리구나!

ES2022

Top-level await

기존에는 async/await은 한 세트로, await을 사용하기 위해서는 최상단에 항상 async를 적어줬어야했는데
2022버전부터는 최상위 레벨에서 await을 사용할 수 있게 되었다. 즉 모듈을 큰 async function처럼 작동하게 해준다.

// 기존
(async () => {
	await AsyncFunction();
})

// 변경
(() => {
	await AsyncFunction();
}

Array.prototype.at()

드디어 Array의 값으로 index를 사용할 때 음수를 사용할 수 있게 되었고, 드디어 Array의 마지막 값을 불러올 때 length를 구해서 array[length-1] 이런식으로 안해도 되게 되었다..만세!

// 기존
let arr = [1, 10, 100, 1000];
let length = arr.length;
console.log(arr[length-1]); // 1000


// 변경
let arr = [1, 10, 100, 1000];
console.log(arr.at(-1)); // 1000

Object.hasOwn()

기존의 Object.hasOwnProperty() 메서드와 거의 비슷한 역할을 하지만 이 메서드는 Object의 프로토타입에 종속된 메서드이기 떄문에, 프로토타입이 없거나 재정의된 객체에서는 사용 불가능하다는 단점이 있었다.
이번에 추가된 Object.hasOwn()은 정적 메서드로 구현되어 특정 인스턴스의 프로토타입 상속 관계에 구애받지 않고 사용 가능하다는 장점이 있다.

let obj = {
	props: "속성"
}

console.log(Object.hasOwn(obj, "props")) // true

Error.prototype.cause

Error.prototype.cause는 에러체이닝을 위해 도입된 속성이다.
예뢰를 잡아서 다시 예외를 발생시킬 때 원래 발생한 오류에 접근할 수 있고, 보다 구체적인 혹은 유용한 에러 메세지를 추가할 때 사용한다.

function job1() {
    
    try {
        job2()
    } catch (e) {
        throw new Error("job1 Error", {cause: e})
    }
    function job2() {
        throw new Error("job2 Error", {cause: "i don't know"})
    }
}

try {
    job1();
} catch (e) {
    console.log(e);
    console.log(e.cause)
}
/*

Error: job1 Error
    at job1 (/Users/han/Desktop/coding/Algorithm/algorithm.js:6:15)
    at Object.<anonymous> (/Users/han/Desktop/coding/Algorithm/algorithm.js:14:5)
    ... 5 lines matching cause stack trace ...
    at node:internal/main/run_main_module:23:47 {
  [cause]: Error: job2 Error
      at job2 (/Users/han/Desktop/coding/Algorithm/algorithm.js:9:15)
      at job1 (/Users/han/Desktop/coding/Algorithm/algorithm.js:4:9)
      at Object.<anonymous> (/Users/han/Desktop/coding/Algorithm/algorithm.js:14:5)
      at Module._compile (node:internal/modules/cjs/loader:1149:14)
      at Module._extensions..js (node:internal/modules/cjs/loader:1203:10)
      at Module.load (node:internal/modules/cjs/loader:1027:32)
      at Module._load (node:internal/modules/cjs/loader:868:12)
      at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
      at node:internal/main/run_main_module:23:47 {
    [cause]: "i don't know"
  }
}
Error: job2 Error
    at job2 (/Users/han/Desktop/coding/Algorithm/algorithm.js:9:15)
    at job1 (/Users/han/Desktop/coding/Algorithm/algorithm.js:4:9)
    at Object.<anonymous> (/Users/han/Desktop/coding/Algorithm/algorithm.js:14:5)
    at Module._compile (node:internal/modules/cjs/loader:1149:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1203:10)
    at Module.load (node:internal/modules/cjs/loader:1027:32)
    at Module._load (node:internal/modules/cjs/loader:868:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47 {
  [cause]: "i don't know"
}
*/

Regexp Match Indices

정규 표현식의 d flag를 사용하면 패턴과 일치하는 문자의 시작과 끝 위치 정보를 얻을 수 있다.
기존에 특정 패턴과 일치하는 문자의 정보를 얻기 위해선 RegExp.prototype.exec 메서드를 사용했는데, 이 메서드는 일치하는 문자의 시작 인덱스 정보만을 제공한다는 단점이 있었다. 이러한 단점을 d flag를 사용하여 해결할 수 있으며, 일치하는 문자열에 대한 인덱스 정보는 .indices속성 안에 포함되어있다.


// 기존 
const target = "bannana apple sweettomato";
const regExp = /\w{2}ple/g; // d flag 추가

const example = regExp.exec(target);
console.log(example);
/* =>
[
  'apple',
  index: 8,
  input: 'bannana apple sweettomato',
  groups: undefined
]
*/

// 변경
const target = "bannana apple sweettomato";
const regExp = /\w{2}ple/gdm; // d flag 추가

const example = regExp.exec(target);
console.log(example);
/* => 
[
  'apple',
  index: 8,
  input: 'bannana apple sweettomato maple',
  groups: undefined,
  indices: [ [ 8, 13 ], groups: undefined ]
]
*/

Class Fields + Private fields check

이번 ES2022에서 가장 많은 변화가 있다는 Class Fields다.


Class Public Instance Fields
인스턴스 프로퍼티를 constructor 외부에서 선언할 수 있게 되었다.
기존에는 속성명 앞에 _를 붙여 private 속성임을 암묵적으로 표시해 주었지만, 앞으로는 #을 사용해 private 속성을 정의할 수 있다. 이 때 private 속성의 값을 외부로부터 주입받고 싶다면, 클래스 몸체에서 우선 정의를 해줘야한다.

class Person {
  canFly = false;
  #age;

  constructor(name, age, phoneNumber) {
    this.name = name;
    this.#age = age;
    this.#phoneNumber = phoneNumber; // Uncaught SyntaxError: Unexpected identifier

    console.log(this.#age); // 17
  }
}

const me = new Person("Jihoon", 17, "010-1111-2222");

console.log(me.isWorking); // false
console.log(me.name); // Jihoon
console.log(me.#age); // Uncaught SyntaxError: Private field '#age' must be declared in an enclosing class

Private Instance methods and accessors
인스턴스 프로퍼티뿐만 아니라 메서드와 접근자 프로퍼티(getter/setter)도 private 속성으로 정의할 수 있게 되었다.

class Person {
    #job;
  
    get #job() {
    	return this.#job;
	}
    
    set #job(work) {
    	this.#job = job;
	}
    
    constructor(work) {
      this.#work = work;
    }

Static class fields and private static methods
기존에는 클래스의 static 메서드는 클래스 몸체 밖에서 정의하였는데 앞으로는 static 키워드를 붙이는 것만으로 간단하게 static 메서드를 정의할 수 있다. (#을 붙임으로써 private으로 사용 가능)

class DailyFruit {
  static #fruit = 'apple';
  static amount = 5;

  static getDailyFruit() {
    return this.#fruit;
  }

  static #getDailyFruitAmount() {
    return this.amount;
  }
}

console.log(DailyFruit.getDailyFruit()); //'apple'
console.log(DailyFruit.amount); // 5
console.log(DailyFruit.#fruit); // SyntaxError
console.log(DailyFruit.#getDailyFruitAmount()); // SyntaxError

Ergonomic brand checks for Private Fields
private 필드가 존재하는 지를 클래스 내부에서 in 키워드를 통해 확인할 수 있다.

class Animal {
  #mammal;
  #amphibian;
  #reptile;
  
  static isExists(obj) {
    return #mammal in obj && #amphibian in obj && #reptile in obj
  }
}

const animal = new Animal();

Animai.isExists(animal);

참고

profile
작게라도 꾸준히 성장하는게 목표입니다.
post-custom-banner

0개의 댓글