본문 바로가기

FRONT/JS

ECMAScript2021 - 최신 JS 기능 5가

들어가기 전..

 

안녕하세요 오랜만에 포스팅하게 되었습니다!

아래 영상을 보고 정리 및 공유하게 되었습니다 ☺

 

 

 


String.prototype.replaceAll

어떤 패턴에 일치하는 모든 부분이 교체된 새로운 문자열을 반환합니다.

기존 replace 에서 문자열 안에 있는 글자를

다른 글자로 모두 대체 하려면 정규표현식을 사용했어야 했습니다.

replaceAll 사용 방법은 아래와 같습니다.

const txt = 'money plz..uu..';
console.log(txt.replaceAll('u','^')); //money plz..^^..

 


 

Promise.any()

iterable(반복 가능한 Array 객체)Promise들 중 하나라도 성공하면

첫 번째로 성공한 Promise의 결과값을 반환하며 단락됩니다.

모든 Promise가 실패하면 에러를 출력합니다.

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

// console = first
Promise.any(anySuccessPromises)
.then(value => console.log(value))
.catch(error => console.error(error));

 

Promise.any async/await 환경과 일반 환경에서 사용할 수 있습니다.

// async/await
(async functon(){
	try {
		const first = await Promise.any(promises);
		// Promise 중 하나라도 성공한 경우
	} catch (error) {
		// 모든 Promise가 실패한 경우
	}
})()

// default
Promise.any(promises).then(
	(first) => {
		// Promise 중 하나라도 성공한 경우
	},
	(error) => {
		// 모든 Promise가 실패한 경우
	}
)

 


 

WeakRefs and Finalizers

WeakRefs

약한 참조(Weak References)를 의미하며 신중하게 사용을 해야 합니다.

가능한 사용하지 않는 것이 좋다고 합니다..

그렇다면 왜 만들어낸 것인가..

 

WeakRefs의 주요 용도는 캐시 또는 대형 개체를 보유하는 매핑을 구현하는 것입니다.

드물게 사용되는 캐시나 매핑을 저장하는데에 있어

오랜 시간동안 메모리를 유지하고 싶지 않은 경우 사용합니다.

 

javascript는 가비지 컬렉터(하단 참조 참고)가 끊임없이 동작하며

도달할 수 없는 객체를 메모리에서 제거합니다.

WeakRefs는 약한 참조이기에 해당 객체에 일반 참조가 없다면 (약한 참조가 있더라도)

가비지 컬렉터가 자동으로 해당 객체를 메모리에서 제거합니다.

let testObj = {
	text: 'Bbosong',
};

const testWeekRef = new WeakRef(testObj);

const printText = () => {
  console.log(testWeekRef.deref().text);
};

testObj = null;

const test = setInterval(printText, 3000);

 

위 코드는 testObj를 testWeekRef라는 변수에 WeakRef를 사용하여 약한 참조 했습니다.

printText 함수에서 deref(약한 참조를 읽는 메서드) 약한 참조 testWeekRef의 text 프로퍼티를 출력하도록 했습니다.

일반 참조를 없애기 위해 testObj 값에 null 을 넣어줘 일반 참조는 사라지고 약한 참조인 testWeekRef 만 남았습니다.

setInterval을 통해 3초에 한번씩 printText를 호출하도록 했습니다.

Bbosong
Bbosong
TypeError: Cannot read property 'name' of undefined

한두번까지는 정상적으로 'Bbosong'이 출력되고 이후로 오류가 발생한다고 하는데

자바스크립트 코드가 실행되는 환경 마다 차이가 있을 수 있습니다.

일반 참조가 제거 되었기 때문에 가비지 컬렉터가 해당 객체를 메모리에서 지우지만

가비지 컬렉터가 메모리를 지우는데도 시간이 걸리기 때문에

한두번 출력까지는 메모리가 남아 있다가 이후에 제거된 것입니다.

왜 제 컴퓨터에서는 200번 넘게까지 정상 출력 되는지 모르겠습니다.

 

참고 : Javascript garbage collection 대한 MDN 내용

참고 : https://ko.javascript.info/weakmap-weakset

 


 

Finalizers

FinalizersFinalizationRegistry의 동반 기능이며
주요 용도는 객체가 가비지 수집된 후 호출된 콜백을 등록할 수 있습니다.

const registry = new FinalizationRegistry((value) => {
  console.log(value);
});

여기서 'registry'는 FinalizationRegistry의 인스턴스이며

FinalizationRegistry에 전달된 콜백 함수는 개체가 가비지 수집될 때 실행됩니다.

 

(function () {
  const obj = {};
  registry.register(obj, "test");
})();

registry.register(obj, "test"); 문항은 
obj가 가비지 수집되면 register 메소드의 두번째 인수(test)가 콜백 함수에 전달됩니다.
따라서 코드 논리에 따르면 obj가 가비지 수집될 떼 "test"가 콜백 함수에 전달되고 콘솔에 출력됩니다.

Google Chrome Canary 콘솔에서 위의 코드를 실행하면 약 1분 후에 콘솔에 'test'가 출력됩니다. 
크롬의 또 다른 방법은 성능 탭에 있는 수집 쓰레기 아이콘을 클릭하여 강제로 가비지 컬렉션 지우는 것입니다

 


 

Logical assignment operators

논리 할당 연산자

기존 논리 연산자(OR, AND, NOT)와 할당연산자(=, +=, -=) 두 연산자를 결합되었다고 이해하심 될 것입니다.

 

아래와 같이 새로운 연산자가 생겼습니다.

  • a ||= b (논리적 OR 할당)
  • a &&= b (논리적 AND 할당)
  • a ??= b (논리적 무효 할당)

 

 

||= (논리적 OR 할당)

첫 번째(왼쪽) 피연산자의 값이 거짓이면 오른쪽 피연산자의 값이 할당합니다

아래와 같은 내용과 유사합니다.

if(!a) {
 a = b
} //before

a ||= b //after

 

예를 들자면.. current_page 라는 변수의 값이 없을 시 default 값으로 넣어줘야 할 때?

(vue 기준 v-if로 탭 기능을 제공하며 탭 마다 각각의 api를 불러와야 할 때)

// 기존 방식 1
if(!this.current_page) {
	this.current_page = this.default_page
}

// 기존 방식 2
this.current_page = !this.current_page ?? this.default_page : this.current_page

// logical assignment operators
this.current_page ||= this.default_page

 


 

&&= (논리적 AND 할당)

첫 번째(왼쪽) 피연산자의 값이 참이면 오른쪽 피연산자의 값이 할당합니다.

아래와 같은 내용과 유사합니다.

if(a) {
 a = b
} //before

a &&= b //after

 

이것을 어떻게 예시를 들까 하다가..

인피니티 스크롤의 first get list 개념으로 예를 드는게 그나마 제일 맞다고 판단이 되어 작성합니다.

(사실 그냥 false 라고 처리해버려도 되지만 억지로 예시를 듭니다)

// 기존 방식 1
if(this.first_list) {
	this.first_list = false
}

// 기존 방식 2
this.first_list = this.first_list ?? false : true

// logical assignment operators
this.first_list ||= false

 


 

??= (논리적 무효 할당)

첫 번째(왼쪽) 피연산자의 값이 null이거나 정의되지 않는 경우 오른쪽 피연산자의 값이 할당합니다.

아래와 같은 내용과 유사합니다.

if(typeof a === 'undefined' || a === null) {
 a = b
} //before

a ??= b //after

 

예를 들자면.. api에서 내려와야 하는 key 값이 없거나 빈 값으로 내려오면 default 값을 넣어야 할 때 사용할 수 있을 것 같습니다.

// 기존 방식 1
if(typeof res.like === 'undefined' || res.like === null) {
	res.like = 0
}

// 기존 방식 2
res.like = res.like === undefined || res.like === null ?? 0 : res.loke

// logical assignment operators
res.like ??= 0

 


 

Numeric separators

Underscore(_)로 숫자 그룹을 시각적으로 구분하여 읽기 쉽게 만들어줍니다.

100000000을 읽으라 하면 눈에 잘 들어오지 않지만 아래와 같이 작성 할 시 시각적 구분이 편합니다

const num = 100_000_000

 

Numeric separators는 순전히 시각적 구분을 위할 뿐 기능에 영향을 미치지 않습니다.

구분 기호가 있는 숫자와 없는 숫자를 비교하면 결과는 true입니다.

console.log(100_000_000 === 100000000) //true

 

Underscore는 숫자 의 아무데나 사용할 수 있지만 맨 앞이나 맨 뒤에서는 오류가 발생합니다.

console.log(123_00_) //숫자 리터럴 끝에 숫자 구분 기호를 사용할 수 없다.
console.log(_123) //_123 is not defined. **_로 숫자를 시작하면 js는 변수로 취급한다**
console.log(0_123) //선행 0 뒤에 숫자 구분 기호를 사용할 수 없다.

이 외 BigInt 리터럴, 이진 리터럴, 8진 리터럴, 16진수 리터럴 에도 사용할 수 있지만

실무에서 잘 쓰일 경우가 없으니 skip 하겠습니다.

 


틀린 내용이 있다면 코멘트 부탁드립니다!

'FRONT > JS' 카테고리의 다른 글

런타임/컴파일타임/SWC/Vite/Deno/Bun  (0) 2023.01.05
Array prototype methods  (0) 2020.05.29