JaeYeopHan / tip-archive

📦 Archiving various development tips. If you watch this repository, you can get issues related to the newly registered development tip from the GitHub feed.
https://www.facebook.com/Jbee.dev/
245 stars 8 forks source link

[Google I/O 2019] What’s new JavaScript? #49

Open JaeYeopHan opened 5 years ago

JaeYeopHan commented 5 years ago

[Google I/O 2019] What’s new JavaScript?

2019년에도 어김없이 Google I/O 행사가 있었습니다. 유익한 수많은 세션 중 What’s new in JavaScript? 을 듣고 정리해봤습니다.

구글은 JavaScript의 스펙을 정하는 Vendor 사 중 한 회사입니다. tc39라는 위원회에도 많은 구글 개발자가 있는 것으로 알고 있습니다. tc39 위원회에서는 ECMAScript라고 불리는 JavaScript의 명세(스펙)를 정의합니다. 현재도 여러 제안들이 올라와 있는데요, tc39/proposals 저장소에서 확인할 수 있습니다.

보다 자세한 JavaScript 스펙이 정해지는 과정은 안희종님의 ECMAScript와 TC39 글을 추천합니다.

TL;DR

summary

바쁘신 분들을 위해 요약 먼저 투척합니다.

지금부터 소개하는 모든 기능 및 명세들은 Chrome 기준 구현이 완료되었으며 타 브라우저를 지원하기 위해서는 폴리필이 필요합니다.

Class fields

ECMAScript 5에서부터 추가됐던 class 문법에 field 영역 관련 문법이 추가됐습니다. 이미 private field에 대해서는 proposal 단계에서부터이야기가 많았습니다.

stop_this_proposal

https://github.com/tc39/proposal-private-methods/issues/10

멤버 변수(클래스 내에서 사용하는 변수)에 private임을 명시하기 위해 자바스크립트 개발자들은 암묵적으로 앞에 underscore(_)를 추가하곤 했습니다. 물론 코드 상으로는 아무 소용없는 convention에 불과합니다. TypeScript를 비롯한 다른 언어에서는 대부분 private이라는 reserved keyword를 통해 클래스 내에서만 접근할 수 있는 private member variable을 정의하지만 JavaScript에서는 #을 사용하여 정의하도록 스펙이 구현됐습니다.

AS-IS

class IncreasingCounter {
  constructor() {
    this._count = 0;
  }
  get value() {
    return this._count;
  }
}
const counter = new IncreasingCounter()
console.log(counter._count) // 0

TO-BE

public member variable

class IncreasingCounter {
  counter = 0;
  get value() {
    return this.count;
  }
}

private member variable

class IncreasingCounter {
  #count = 0;
  get value() {
    return this.count;
  }
}
const counter = new IncreasingCounter()
counter.count // Syntax Error

Node 런타임 환경에서도 LTS version에는 이미 구현이 완료된 스펙입니다. (😢)

String.matchAll

이미 정규표현식을 위한 match API는 구현이 되어있었습니다. 이 matchAll API는 capturing group을 함께 반환합니다.

AS-IS

const longString = 'Magic hex number: DEFAD CAFE'
const regex = '/\b\p{ASCII_Hex_Digit}+\b/gu'

for (const match of string.match(regex)) {
  console.log(match)
}

// => Output
// 'DEFAD'
// 'CAFE'

TO-BE

const longString = 'Magic hex number: DEFAD CAFE'
const regex = '/\b\p{ASCII_Hex_Digit}+\b/gu'

for (const match of string.matchAll(regex)) {
  console.log(match)
}

// => Output
// ['DEFAD', index: 19, input: '...']
// ['CAFE', index: 19, input: '...']

Large numeric value

큰 정수의 가독성을 높이기 위해 추가된 숫자 형식입니다. 세 자리 수마다 _를 통해 구분지을 수 있습니다.

10000000 => 10_000_000

역시 babel의 플러그인을 통해 사용할 수 있습니다.

BigInt

JavaScript가 핸들링 할 수 있는 정수의 범위보다 큰 정수를 다룰 때 BigInt가 추가됐습니다.

1234567890123456789 * 123
// 151851850485185200000 -> Not correct!
BigInt(1234567890123456789) * 123n
//151851850485185182464n

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/BigInt

Array.flat / Infinity

이 API도 사건이 있었습니다. 일명 SmoothGate. flat API 이름이 smoosh로 오해한(?) 사건입니다. 관련 내용은 구글이 정리해둔 자료가 있어 첨부합니다. (#smooshgate FAQ)

flat API는 중첩된 배열을 ‘평평하게’ 풀 수 있는 API입니다. 기존에도 많은 라이브러리가 있었는데요, 이번에 스펙으로 포함됐습니다.

// Flatten one level
const array = [1, [2, [3]]]
array.flat()
// -> [1, 2, [3]]

array.flat(Infinity)
// -> [1, 2, 3]

Object.entries()

iterable 한 [key, value]를 반환하는 API입니다. enumerable 속성에 대하여 반환하며 순서는 object에 명시된 그 순서와 동일합니다. 이 API를 사용하여 object를 Map 자료구조로 쉽게 변환할 수 있게 됐습니다. 반대의 API로 fromEntries() API도 존재합니다.

const object = { lang: 'JavaScript', coolness: 9001 }
// Convert the object into a map
const map = new Map(Object.entries(object))
// Convet map into a object
const reObject = Object.fromEntries(map)

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/entries https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries

globalThis

JavaScript 개발자가 전세계적으로 정말 많다보니 이 스펙도 논의가 많았습니다.

please_use_name_without_this

JavaScript에서 this는 골칫거리로 유명한데요, 브라우저인지 node.js 환경인지에 따라서 그 대상이 바뀌기 때문입니다. 이러한 이슈로 여러 라이브러리도 있었고 폴리필도 있었습니다. 이러한 문제를 해결하기 위해 아예 전역 this 를 제공하는 스펙입니다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/globalThis

Intl

Intl.RelativeTimeFormat

const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }); // 'ko' is available

rft.format(-1, 'day') // yesterday
rft.format(0, 'day') // today
rft.format(1, 'day') // tomorrow

Intl.ListFormat

const lfEnglish = new Intl.ListFormat('en', { type: 'disjunction'} );
lfEnglish.format(['a', 'b']) // 'a or b'

Intl.DateTimeFormat

const fmt = new Intl.DateTimeFormat('en', {
  year: 'numeric'
  month: 'long'
  day: 'numeric'
});
const output = fmt.formatRange(date1, date2)
// 'May 7 - 9, 2019'

Intl은 이외에도 여러 API가 있습니다.

Promise

기존에도 유용한 두 API(Promise.all, Promise.race)가 존재했습니다. 여기서 다음 두 API가 추가됐습니다. 정말 쉽게 풀어써보면 다음과 같은 API가 됩니다.

+Promise.allSettled

실패(rejected)든 성공(settled)이든 모든 게 다 끝날 때.

+Promise.any

실패(rejected)든 성공(settled)이든 가장 빠른 어떤 것 하나가 끝날 때.

ETC

마무리

추가되는 JavaScript 스펙을 알아봤습니다.

여담.

슬라이드에 Angular는 어디가고 React가...🤭

Screen Shot 2019-05-29 at 1 38 44 PM