ECMASript 2015(ES6) 이후 자바스크립트 기능들을 소개합니다.
[1].includes(1); // true
2**10 // 1024
async getData() {
const res = await api.getTableData(); // await asynchronous task
// do something
}
Object.values({a: 1, b: 2, c: 3}); // [1, 2, 3]
Object.entries({a: 1, b: 2, c: 3}); // [["a", 1], ["b", 2], ["c", 3]]
let user = { name: "John"};
let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
console.log(JSON.stringify(descriptor, null, 2));
/* property descriptor:
{
"value": "John",
"writable": true,
"enumerable": true,
"configurable": true
}
*/
/**
** @param {*} length The size of the array buffer created, in bytes.
** @Returns {ShareDarrayBuffer} A new ShareDarrayBuffer object of specified size. Its contents are initialized to 0. */
new SharedArrayBuffer(10)
MDN SharedArrayBuffer
만화로 소개하는 ArrayBuffer 와 SharedArrayBuffer
"hello".padStart(6); // " hello"
"hello".padEnd(6); // "hello "
"hello".padStart(3); // "hello" // 문자열 길이보다 목표 문자열 길이가 짧다면 채워넣지 않고 그대로 반환
"hello".padEnd(20, "*"); // "hello***************" // 사용자가 지정한 값으로 채우는 것도 가능
function f(p) {}
function f(p,) {}
(p) => {};
(p,) => {};
for-await-of
async function process(array) {
for await (let i of array) {
// doSomething(i);
}
}
Promise.resolve().then().catch(e => e).finally();
const myObj = { a: 1, b: 3, c: 'cc', d: 100 };
const {a, b, ...z} = myObj;
console.log(z); // { "c": "cc", "d": 100 }
const spread = { ...myObj, a: 10, e: 30,};
console.log(spread); // { "a": 10, "b": 3, "c": "cc", "d": 100, "e": 0 }
1) RegExp lookbehind assertions
// ?= 특정 하위 문자열이 뒤에 오는 문자열을 일치시키는데 사용
/Roger(?=Waters)/
/Roger(?= Waters)/.test('Roger is my dog') //false
/Roger(?= Waters)/.test('Roger is my dog and Roger Waters is a famous musician') //true
// ?! 문자열 뒤에 특정 하위 문자열이 오지 않는 경우 일치하는 역 연산을 수행
/Roger(?!Waters)/
/Roger(?! Waters)/.test('Roger is my dog') //true
/Roger(?! Waters)/.test('Roger Waters is a famous musician') //false
// ?<= 새로 추가된 표현식
/(?<=Roger) Waters/
/(?<=Roger) Waters/.test('Pink Waters is my dog') //false
/(?<=Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician') //true
// ?<! 새로 추가된 표현식
/(?<!Roger) Waters/
/(?<!Roger) Waters/.test('Pink Waters is my dog') //true
/(?<!Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician') //false
2) 유니코드 속성 이스케이프 \p{…}
및 \P{…}
// ASCII
/^\p{ASCII}+$/u.test('abc') //✅
/^\p{ASCII}+$/u.test('ABC@') //✅
/^\p{ASCII}+$/u.test('ABC🙃') //❌
// HEX
/^\p{ASCII_Hex_Digit}+$/u.test('0123456789ABCDEF') //✅
/^\p{ASCII_Hex_Digit}+$/u.test('h') //❌
// Emoji, ppercase, Lowercase, White_Space, Alphabetic
/^\p{Lowercase}$/u.test('h') //✅
/^\p{Uppercase}$/u.test('H') //✅
/^\p{Emoji}+$/u.test('H') //❌
/^\p{Emoji}+$/u.test('🙃🙃') //✅
// Script
/^\p{Script=Greek}+$/u.test('ελληνικά') //✅
/^\p{Script=Latin}+$/u.test('hey') //✅
3) 명명된 캡처 그룹(named capture group)
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
const result = re.exec('2015-01-02')
// result.groups.year === '2015';
// result.groups.month === '01';
// result.groups.day === '02';
4) s
플래그(dotAll)
.
표현식은 개행문자를 제외한 모든 문자였으나, s
플래그를 달면 개행식도 포함하게 된다./hi.welcome/.test('hi\nwelcome') // false
/hi.welcome/s.test('hi\nwelcome') // true
// flat()
['Dog', ['Sheep', 'Wolf']].flat()
//[ 'Dog', 'Sheep', 'Wolf' ]
// flatMap()
let arr1 = ["it's Sunny in", "", "California"];
arr1.map(x=>x.split(" "));
// [["it's","Sunny","in"],[""],["California"]]
arr1.flatMap(x => x.split(" "));
// ["it's","Sunny","in", "", "California"]
try {
//...
} catch /*(e)*/ {
//handle error
}
const entries = new Map([
['foo', 'bar'],
['baz', 42]
]);
const obj = Object.fromEntries(entries);
console.log(obj);
// expected output: Object { foo: "bar", baz: 42 }
// trimStart()
'Testing'.trimStart() //'Testing'
' Testing'.trimStart() //'Testing'
' Testing '.trimStart() //'Testing '
'Testing '.trimStart() //'Testing '
// trimEnd()
'Testing'.trimEnd() //'Testing'
' Testing'.trimEnd() //' Testing'
' Testing '.trimEnd() //' Testing'
'Testing '.trimEnd() //'Testing'
Symbol('desc').toString(); // "Symbol(desc)"
Symbol('desc').description; // "desc"
JSON.stringify("\uD800"); // 변경 전 --> '"�"' // 잘못된 형식의 유니코드 문자를 반환
JSON.stringify("\uD800"); // 변경 후 --> '"\ud800"' // 유효한 유니코드를 반환
toString()
메서드는 함수의 소스 코드를 나타내는 문자열을 반환한다.function /* this is bar */ bar() {}
// old
bar.toString() //'function bar() {}
// new
bar.toString() // 'function /* this is bar */ bar () {}'
BigInt와 Number는 어떤 면에서 비슷하지만 중요한 차이점이 있습니다. 예컨대 BigInt는 내장 Math객체의 메서드와 함께 사용할 수 없고, 연산에서 Number와 혼합해 사용할 수 없습니다. 따라서 먼저 같은 자료형으로 변환해야 합니다. 그러나, BigInt가 Number로 바뀌면 정확성을 잃을 수 있으니 주의해야 합니다. 또한 bigDecimal이 아니기 때문에 소수점 이하는 언제나 버립니다.
const theBiggestInt = 9007199254740991n;
const bigintSum = theBiggestInt + 1n; // 9007199254740992n
const alsoHuge = BigInt(9007199254740991); // 9007199254740991n
typeof bigintSum // "bigint"
if (condition1 && condition2) {
const module = await import('./path/to/module.js');
module.doSomething();
}
?.
연산자는 .
체이닝 연산자와 유사하게 작동하지만, 만약 참조가 nullish(null 또는 undefined)이라면, 에러가 발생하는 것 대신에 표현식의 리턴 값은 undefined로 단락된다. 함수 호출에서 사용될 때, 만약 주어진 함수가 존재하지 않는다면, undefined를 리턴한다.const adventurer = {
name: 'Alice',
cat: { name: 'Dinah' }
};
const catName = adventurer.cat?.name; // 'Dinah'
const dogName = adventurer.dog?.name; // undefined
const promiseArr = [
new Promise((resolve, reject) => setTimeout(resolve, 1000, 'abc')),
new Promise((resolve, reject) => setTimeout(reject, 2000)),
new Promise((resolve, reject) => setTimeout(resolve, 3000)),
];
Promise.allSettled(promiseArr).then(data => console.log(data));
[
{
"status": "fulfilled",
"value": "abc"
},
{
"status": "rejected"
},
{
"status": "fulfilled"
}
]
let user = { u1: 0, u2: false, u3: null, u4: undefined u5: '', }
let u1 = user.u1 ?? 'user 1' // 0
let u2 = user.u2 ?? 'user 2' // false
let u3 = user.u3?? 'user 3' // user 3
let u4 = user.u4?? 'user 4' // user 4
let u5 = user.u5?? 'User 5' // ''
const regexp = /t(e)(st(\d?))/g;
const str = 'test1test2';
const array = [...str.matchAll(regexp)];
console.log(array[0]); // expected output: Array ["test1", "e", "st1", "1"]
console.log(array[1]); // expected output: Array ["test2", "e", "st2", "2"]
export * as A from "./moduleA";
export * as B from "./moduleA";
import { A, B } from "./modules";
console.log(A.a); // 1
console.log(A.b); // 2
console.log(B.b); // 3
console.log(B.c); // 4
<script type="module" src="my-module.js">
console.log(import.meta); // { url: "file:///home/user/my-module.js" }
// browser environment
console.log(globalThis); // => Window {...}
// node.js environment
console.log(globalThis); // => Object [global] {...}
// web worker environment
console.log(globalThis); // => DedicatedWorkerGlobalScope {...}
g
옵션을 통해 전역으로 적용하지 않고도 문자열의 지정한 모든 문자열을 특정 문자열의 값으로 변경한다.const str = 'hello world';
str.replaceAll('l', ''); // "heo word"
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')),
];
// first
Promise.any(anySuccessPromises)
.then(value => console.log(value))
.catch(error => console.error(error));
const allFailurePromises = [
new Promise((res, rej) => setTimeout(rej, 100, 'first')),
new Promise((res, rej) => setTimeout(rej, 200, 'second')),
new Promise((res, rej) => setTimeout(rej, 300, 'third')),
];
// AggregateError: All promises were rejected
Promise.any(anySuccessPromises)
.then(value => console.log(value))
.catch(error => console.error(error));
class Counter {
constructor(element) {
// Remember a weak reference to the DOM element
this.ref = new WeakRef(element);
this.start();
}
start() {
if (this.timer) {
return;
}
this.count = 0;
const tick = () => {
// Get the element from the weak reference, if it still exists
const element = this.ref.deref();
if (element) {
element.textContent = ++this.count;
} else {
// The element doesn't exist anymore
console.log("The element is gone.");
this.stop();
this.ref = null;
}
};
tick();
this.timer = setInterval(tick, 1000);
}
stop() {
if (this.timer) {
clearInterval(this.timer);
this.timer = 0;
}
}
}
const counter = new Counter(document.getElementById("counter"));
setTimeout(() => {
document.getElementById("counter").remove();
}, 5000);
// before
obj.prop = obj.prop || foo(); // obj.prop이 잘못된 값일 경우 할당
obj.prop = obj.prop && foo(); // obj.prop이 올바른 값일 경우 할당
obj.prop = obj.prop ?? foo(); // obj.prop이 null이나 undefined일 경우 할당
// after
obj.prop ||= foo();
obj.prop &&= foo();
obj.prop ??= foo();
// before
10000000000 // 100억
// after
10_000_000_000 // 100억
console.log(10_000_000_000); // 10000000000
ES2022는 2022년 6월에 출시되며 2022년 3월까지 4단계에 도달한 모든 아이디어는 JavaScript에 포함될 예정이다.
import {getUser} from "./data/User"
let user = await getUser();
class hello {
fields = 0;
title;
}
#
기호를 접두사로 사용하여 private 클래스 필드를 직접 선언할 수 있다.class hello {
fields = 0;
#title;
get #title() { return #title; }
set #title() { #title = null; }
}
class hello {
name;
static title = 'here';
static get title() { return title; }
}
d
문자를 활용하여 일치하는 문자열의 시작 및 끝 인덱스가 있는 배열을 얻을 수 있다.const re1 = /a+(?<Z>z)?/d;
// indices are relative to start of the input string:
const s1 = "xaaaz";
const m1 = re1.exec(s1);
m1.indices[0][0] === 1;
m1.indices[0][1] === 5;
s1.slice(...m1.indices[0]) === "aaaz";
in
연산자를 사용하여 특정 클래스에 필드가 있는지 여부를 간단히 확인할 수 있다.
class hello{
name;
#title;
get #title() {
return #title;
}
set #title() {
#title=null;
}
static hasTitle(obj1) {
return #title in obj1;
}
}
at()
함수를 사용하여 양수 및 음수 인덱스를 모두 사용하여 문자열을 인덱싱할 수 있다.array= [1.2.4.5]
console.log(array[array.length-1]);
console.log(array.at(-1));
hasOwn()
추가const obj1={ hello:'Hi' }
let hasHello1=Object.prototype.hasOwnProperty.call(obj1, 'hello');
let hasHello= obj1.hasOwn(obj1, 'hello'); //
console.log(hasHello);
console.log(hasHello1);
ES6 이후의 변경점 총정리
New features for JS syntax ES6, ES7, ES8, ES9, ES10, ES11, ES12
what's new in es2022?