자바스크립트 ES2021(ES12)에서 추가된 5가지 주요 기능들

1. String.prototype.replaceAll() 메서드

그동안 자바스크립트 개발자들이 주야장천 요청해왔던 기능이었는데 이제야 추가되었습니다.

일치하는 모든 문자열을 변경합니다.

자바스크립트 내장 문자열 변경 메서드인 "String.prototype.replace()"는 처음 나오는 일치하는 문자열만 바꾸는 것이기 때문에 여러 가지로 불편했습니다.

대부분 정규표현식으로 프로토타입 메서드를 만들어 써왔기 때문에 사실 없다는걸 알아도 나름대로는 다 개선을 해서 써왔습니다.

내장 메서드로 지원을 하므로 더 이상 추가로 구현을 해서 사용하지 않아도 됩니다.

대부분 최신 웹 브라우저에서 이미 지원하고 있습니다.

console.log("문자열에서 여러번 나오는 문자열을 한꺼번에 변경할 수 있습니다.".replaceAll("문자열",""));

2. 논리 대입 연산자 ||=, &&=

다른 언어에 있는 연산자이기 때문에 개념은 동일합니다. 이게 얼마나 쓸모가 있을지는 조금 의문입니다.

이런 복합 연산자는 코드의 논리 비교  결과 대입을 단순하게 줄여주기는 하지만, 가독성을 떨어뜨리고 코드의 흐름을 방해하기도 합니다.

이 두 연산자는 += 연산자처럼 앙 변의 값/변수를 || 또는 && 비교 연산한 결과를 왼쪽의 변수에 대입(=)하는 기능을 합니다.

먼저 자바스크립트에서 빈 문자열 ""과, 숫자 0은 false가 됩니다.

이점을 분명히 기억해야 새로운 복합 연산자의 결과 값 대입을 이해할 수 있습니다.

먼저 ||= 연산자를 알아보겠습니다.

let str = "문자열1";
let bool = false;
console.log(str ||= "문자열"); // "문자열1"
str = "문자열1";
console.log(str ||= false); // "문자열1"
console.log(bool ||= true); // true
console.log(str ||= ""); // "문자열1"
str = "";
console.log(str ||= false); // false
console.log(str ||= true); // true
str = "";
console.log(str ||= "문자열2"); // "문자열2"

||= 연산자는 비교적 이해하기 쉽습니다. 왼쪽의 변수 항이 참에 해당하면 변수의 값이 유지되고, 거짓이면 오른쪽 값이 변수에 대입됩니다. 

주의할 점이 있습니다. 왼쪽 비교 항은 반드시 변수여야 합니다.

당연하지만 ||=, &&= 연산자는 대입 연산자이기 때문에 왼쪽편에 결과 값을 대입할 수 있는 변수가 있어야 합니다.

다음과 같은 표현은 사용할 수 없습니다.

console.log("문자열" ||= str);

다른 예를 들어보겠습니다. 왼쪽 항의 문자열 변수 "str"의 값이 빈 문자열("")이면 얘기가 조금 달라집니다.

다음의 예에서 "str"은 문자열 변수지만, 빈 문자열이기 때문에 거짓이 되고, 오른쪽 항은 불리언 true 이기 때문에 오른쪽 항의 값이 대입되면서 "str" 변수는 불리언 값인 true를 가지고 있는 불리언 변수로 바뀝니다.

변수의 타입과 참일 때 대입되는 오른쪽 항의 타입이 다르면, 오른쪽 타입으로 캐스팅 됩니다.

let str = "";
console.log(str ||= true); // true

&&= 대입 연산자를 알아보겠습니다.

양 변이 모두 참이면 오른쪽 항의 값이 변수에 대입됩니다. 나머지는 왼쪽 항 변수의 값이 유지됩니다.

let str = "문자열1";
let bool = true;

console.log(bool &&= "문자열"); // false
bool = true;
console.log(bool &&= "문자열3"); // "문자열3"
str = "문자열1";
console.log(str &&= "문자열2"); // "문자열2"
str = "";
console.log(str &&= ""); // 빈문자열

논리 AND 대입(&&=)으로 오른쪽 항의 값을 대입할 경우, 변수 타입과 오른쪽 항의 타입이 다르면 오른쪽 항의 타입으로 캐스팅됩니다.

let str = "문자열1"
console.log(str &&= true); // true

3. 숫자 구분자

1000000000과 과 같은 단위가 큰 숫자의 가독성을 높일 수 있게 언더바(_)로 단위를 구분할 수 있는 표현이 허용됩니다.

1_000_000_000과 같이 천 단위로 끊어서 표기를 하는 것이 가능하기 때문에 0의 개수를 일일이 세어 볼 필요 없이 10억이라는 숫자임을 조금 더 쉽게 알 수 있습니다.

구분자는 임의의 위치에 삽입할 수 있습니다.

숫자로 처리되기 때문에 연산도 가능합니다.

console.log(1_000_000_000 + 10_000);
console.log(1_00_00_00 + 10_0);

4. Promise.any() 메서드

여러 개의 프로미스를 담은 배열을 인자로 받아서 배열의 프로미스 중 하나라도 결과가 반환되면 프로미스 조건을 만족하고 종료합니다.

여러 개의 프로미스 비동기 처리 중에서 하나라도 성공하면 모든 조건이 만족한 것으로 처리하는 구조입니다.

지정된 시간 후 문자열을 반환하는 간단한 프로미스를 하나 정의한 후 파라미터로 여러 프로미스를 가진 배열을 만들어서 실행해보겠습니다. 프로미스 배열의 2번째 프로미스가 가장 빨리 결과를 반환하며, 배열의 프로미스는 모두 종료됩니다.

const promise = (delay) => new Promise((resolve) => {
    setTimeout(() => resolve(`${delay} 초 지연 후 실행`), delay*1000);
});
const promises = [promise(4), promise(2), promise(6)];
Promise.any(promises).then((ret) => console.log(ret)); // "2초 지연 후 실행" 문구만 표시되고 종료

5. 클래스 프라이빗 메서드와 필드

이전까지 자바스크립트 클래스의 모든 메서드는 퍼블릭이었습니다. 클래스 외부에서 모두 접근이 가능한 메서드만 생성 가능했습니다. 그래서 유명무실한 반쪽짜리 클래스 구현체로 비난을 받아왔습니다.

ES2021부터는 메서드와 필드명 앞에 "#"을 붙여서 프라이빗 메서드와 필드 정의가 가능합니다. "#"이 붙은 메서드와 필드는 프라이빗으로 동작하면 클래스 외부에서 접근이 되지 않습니다.

class myClass {
    #privField
    #privMethod(){
        return "프라이빗 메서드";
    }
    publicMethod(){
        return "퍼블릭 메서드";
    }    
}

let newClass = new myClass();
console.log(newClass.privMethod());

문자열을 반환하는 간단한 클래스를 정의해서 프라이빗으로 선언한 메서드를 호출하면 다음과 같이 함수가 아니라는 에러가 발생합니다.