이번 포스팅에선 ES11 의 기능들에 대해 알아보겠습니다.
- matchAll
정규표현식에 사용할 수 있는 새로운 메서드가 추가되었습니다.
기존에는 match 메서드를 사용해왔었는데, 어떤 차이점이 있는지 아래 코드 예제로 보도록 하겠습니다.
const regex1 = /https?:\/\/www.npmjs.com\/package\/(\w*)/g;
const regex2 = /https?:\/\/www.npmjs.com\/package\/(\w*)/;
const domain = 'https://www.npmjs.com/package/axios';
const test1 = domain.match(regex1);
const test2 = domain.match(regex2);
console.info(test1); // [ 'https://www.npmjs.com/package/axios' ]
console.info(test2);
/*
[
'https://www.npmjs.com/package/axios',
'axios',
index: 0,
input: 'https://www.npmjs.com/package/axios',
groups: undefined
]
*/
기존 match 메서드에선 정규표현식에 g flag 를 같이 사용한다면 일치하는 요소만 Array 형으로 반환하지만, g flag 를 사용하지 않으면 캡쳐 그룹까지 반환하는 것을 볼 수 있습니다.
const regex = /https?:\/\/www.npmjs.com\/package\/(\w*)/g;
const domain = 'https://www.npmjs.com/package/axios';
const test1 = domain.matchAll(regex);
const test2 = [...test1];
console.info(test1); // Object [RegExp String Iterator] {}
console.info(test2);
/*
[
[
'https://www.npmjs.com/package/axios',
'axios',
index: 0,
input: 'https://www.npmjs.com/package/axios',
groups: undefined
]
]
*/
새로 추가된 matchAll 메서드에선 g flag 를 사용해 동일하게 테스트했을 때, 일치하는 결과에대한 iterator object 가 반환됩니다.
이를 전개연산자를 사용해 풀어보면 index, input, groups 프로퍼티까지 전부 반환하는 것을 볼 수 있습니다.
개인적으론 정규표현식을 자주 사용할 일은 없어서 이 차이점에 대해 크게 체감이 되진 않습니다..
- BigInt
내장 객체 Number 의 안전한 수 최대치는 2^53 - 1 입니다. 이 수를 넘어가면 연산이 제대로 되지 않는 문제가 있는데, 이보다 더 큰 정수를 표현할 수 있는 내장 객체인 BigInt 가 나왔습니다.
const number = Number.MAX_SAFE_INTEGER;
const bigNumber = BigInt(number);
console.info(number); // 9007199254740991
console.info(number * 10); // 90071992547409900
console.info(bigNumber * 10n); // 90071992547409910n
Number.MAX_SAFE_INTEGER 에 *10 연산을 했을 때 기존 Number 로는 정확한 값을 얻을 수 없지만, BigInt 에선 정확한 값을 구할 수 있습니다. 다만 정수 리터럴뒤에 n 표기가 추가되었고, 연산에 사용되는 숫자 뒤에도 n 을 붙여야 합니다.
const number = Number.MAX_SAFE_INTEGER;
const bigNumber = BigInt(number);
console.info(typeof number); // number
console.info(typeof bigNumber); // bigint
console.info(0n === 0); // false
console.info(0n == 0); // true
자료형은 bigint 입니다. 또한 bigint 는 number 와 일치하진 않으나, 동등합니다.
BigInt 를 Number 로 변환하는 것은 과정에서 정확도를 유실할 수 있으므로 권장되지 않습니다.
기존엔 연산의 정확도를 높이거나 더 큰 수에 대한 연산을 할 필요가 있을 경우 BigNumber.js 와 같은 라이브러리의 도움을 받았었는데,
활용하기에 따라 BigInt 로 대체할 수도 있을 것 같습니다.
- Promise.allSettled
Promise.allSettled 메서드는 주어진 모든 프로미스에 대해 fulfilled 되거나 rejected 된 결과를 배열로 반환합니다.
const promise1 = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve(1);
}, 500);
});
};
const promise2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(3);
}, 100);
});
};
(async () => {
try {
const promises = [promise1(), promise2()];
const test1 = await Promise.all(promises);
console.info(test1);
} catch (e) {
console.error(e); // 3
}
})();
Promise.all 의 경우 주어진 프로미스가 하나라도 거부되면 다른 프로미스의 이행 여부에 상관 없이 거부됩니다.
const promise1 = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve(1);
}, 500);
});
};
const promise2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(3);
}, 100);
});
};
(async () => {
const promises = [promise1(), promise2()];
const test1 = await Promise.allSettled(promises);
console.info(test1); // [{ status: 'fulfilled', value: 1 }, { status: 'rejected', reason: 3 }]
})();
Promise.allSettled 의 경우엔 위와 같이 반환하므로 서로 성공 여부에 상관없는 비동기 작업들을 모아서 처리하거나
프로미스가 fulfilled 혹은 rejected 되었는지에 대한 결과만 궁금하다면 사용하기 좋을 것 같습니다.
- asynchronously import Modules
자바스크립트에선 commonJS 스타일로 모듈을 사용할 경우 import 구문을 사용할 수도 없고, 사용한다해도 제약이 꽤 있어 함수안에서 사용도 불가했습니다.
// test-module.js
export function test1() {
console.info('test1');
}
export function test2() {
console.info('test2');
}
// test.js
const tmp = async () => {
const { test1, test2 } = await import('./test-module.js');
test1(); // 'test1'
test2(); // 'test2'
};
tmp();
이제 import 표현식을 위와 같이 코드 내 어디서든 동적으로 사용할 수 있게 되었습니다.
import 앞에 await 때문에 무조건 async 와 같이 사용해야하는가? 라고 생각이 들 수 있지만 그냥 사용도 가능합니다.
워낙에 async - await 는 세트로 다뤘다보니 어색하게 느껴지긴 합니다.
- globalThis
console.info(globalThis);
/*
Object [global] {
global: [Circular *1],
clearInterval: [Function: clearInterval],
clearTimeout: [Function: clearTimeout],
setInterval: [Function: setInterval],
setTimeout: [Function: setTimeout] {
[Symbol(nodejs.util.promisify.custom)]: [Getter]
},
queueMicrotask: [Function: queueMicrotask],
clearImmediate: [Function: clearImmediate],
setImmediate: [Function: setImmediate] {
[Symbol(nodejs.util.promisify.custom)]: [Getter]
}
}
*/
console.info(globalThis === global); // true
일단 환경은 Node.JS 입니다. 전역객체에 접근할 수 있는 통일된 방법이 globalThis 로 나왔습니다.
브라우저 환경이라면, globalThis 는 window 객체와 동일합니다.
정확히 말하자면 globalThis 자체가 전역객체는 아니고, 전역 스코프의 this 를 반환하는 형태입니다.
사실 전역 스코프의 this 에 접근해서 뭘 하는 일은 지금까지 저한텐 거의 없었고, 앞으로도 없지 않을까 싶습니다만 프론트 개발자면 다소 있을 것 같기도 합니다. 또한 환경에 따라 global 을 쓰거나 window 를 써야하는 통일성이 없던 것에 비하면 좋은 변화인 것 같습니다.
그 외엔 import.meta / for-in / nullish 등에 변화가 있지만 마이너한 부분으로 보여 이정도에서 넘어가도록 하겠습니다.
'Backend > Javascript' 카테고리의 다른 글
ES7 (ES2016) (0) | 2022.03.19 |
---|---|
ES12 (ES2021) (0) | 2022.03.13 |
ES10 (ES2019) (0) | 2022.02.27 |
ES9 (ES2018) (0) | 2022.02.19 |
ECMAScript (0) | 2022.02.12 |