tip-archive icon indicating copy to clipboard operation
tip-archive copied to clipboard

[Google I/O 2019] Whatโ€™s new JavaScript?

Open JaeYeopHan opened this issue 5 years ago โ€ข 0 comments

[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

๋ฐ”์˜์‹  ๋ถ„๋“ค์„ ์œ„ํ•ด ์š”์•ฝ ๋จผ์ € ํˆฌ์ฒ™ํ•ฉ๋‹ˆ๋‹ค.

  • Class fields
    • public and private (#)
  • String.mathAll()
  • Large Number with underscore (_)
    • 1000000 === 1_000_000
  • Array.flat()
  • Object.entries()
  • globalThis
  • Intl
    • Intl.RelativeTimeFormat
    • Intl.ListFormat
    • Intl.ListFormat
    • Intl.Locale
  • Promise
    • allSettled
    • any
  • etc
    • Use await on the top-level
    • Array.sort() is stable

์ง€๊ธˆ๋ถ€ํ„ฐ ์†Œ๊ฐœํ•˜๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ ๋ฐ ๋ช…์„ธ๋“ค์€ 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

  • Can use await function on the top-level without async function wrapping early implemented.
    • https://github.com/tc39/proposal-top-level-await
  • Array.sort() is stable

๋งˆ๋ฌด๋ฆฌ

์ถ”๊ฐ€๋˜๋Š” JavaScript ์ŠคํŽ™์„ ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค.

์—ฌ๋‹ด.

์Šฌ๋ผ์ด๋“œ์— Angular๋Š” ์–ด๋””๊ฐ€๊ณ  React๊ฐ€...๐Ÿคญ

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

JaeYeopHan avatar May 29 '19 02:05 JaeYeopHan