Skip to content

Instantly share code, notes, and snippets.

@oiehot
Created April 23, 2017 04:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oiehot/0dba47e9e140a87964d760468097fc86 to your computer and use it in GitHub Desktop.
Save oiehot/0dba47e9e140a87964d760468097fc86 to your computer and use it in GitHub Desktop.
ES6 Features
//
// ES6 Features
//
// 원본: http://es6-features.org
//
// 1. 상수
// =======
const PI = 3.141593
PI = 1.0 // Error
// 2. 범위
// =======
// 블럭 범위 변수
a = [0,1,2,3,4,5]
for (let i=0; i<a.length; i++) {
let x = a[i]
}
// 블럭 범위 함수
{
function foo() { return 1; }
if (foo() === 1) {
function foo() { return 2; }
if (foo() === 2) { console.log("Goal") }
}
}
// 3. 화살표 함수
// =============
evens = [2,4,6,8,10,12]
odds = evens.map(v => v + 1)
pairs = evens.map(v => ({
even: v,
odd: v + 1
}))
nums = evens.map(
(v,i) => v + i
);
// ----
let nums = [0,1,5,9,10,14,15,19,20,25]
let fives = []
nums.forEach(v => {
if (v % 5 === 0) {
fives.push(v)
}
});
// 4. 매개변수
// ==========
// 기본 매개변수 값
function f (x,y = 7, z = 42) {
return x + y + z
}
f(1) === 50
// 나머지 매개변수
function f (x, y, ...a) {
return (x+y) * a.length
}
// 스프레드 연산자
var params = ["hello", true, 7]
var other = [1, 2, ...params] // Append
// 5. 템플릿 리터럴
// ===============
var name = { firstName: "Taewoo", lastName: "Lee" }
var fullName = `${name.firstName} ${name.lastName}`
// ----
let bar = "bar"
let baz = "baz"
let quux = "quux"
console.log( `http://example.com/foo?bar=${bar + baz}&quux=${quux}` )
// Raw 문자열 읽기
function quux (strings, ...values) {
console.log( strings[0] === "foo\n" ) // true
console.log( strings[1] === "bar" ) // true
console.log( strings.raw[0] === "foo\\n" ) // true
console.log( strings.raw[1] === "bar" ) // true
console.log( values[0] === 42 ) // true
}
quux `foo\n${ 42 }bar`
String.raw `foo\n${ 42 }bar` === "foo\\n42bar"
// 6. 확장된 리터럴
// ===============
// 2진, 8진 리터럴
0b111110111 == 503
0o767 == 503
// 유니코드
"𠮷".length === 2
"𠮷".match(/./u)[0].length === 2
"𠮷" === "\uD842\uDFB7"
"𠮷" === "\u{20BB7}"
"𠮷".codePointAt(0) == 0x20BB7
for (let codepoint of "𠮷") console.log(codepoint)
// 7. 정규표현식
// ============
let parser = (input, match) => {
for (let pos = 0, lastPos = input.length; pos < lastPos; ) {
for (let i = 0; i < match.length; i++) {
match[i].pattern.lastIndex = pos
let found
if ((found = match[i].pattern.exec(input)) !== null) {
match[i].action(found)
pos = match[i].pattern.lastIndex
break
}
}
}
}
let report = (match) => {
console.log(JSON.stringify(match))
}
parser("Foo 1 Bar 7 Baz 42", [
{ pattern: /^Foo\s+(\d+)/y, action: (match) => report(match) },
{ pattern: /^Bar\s+(\d+)/y, action: (match) => report(match) },
{ pattern: /^Baz\s+(\d+)/y, action: (match) => report(match) },
{ pattern: /^\s*/y, action: (match) => {} }
])
// 8. 객체 프로퍼티
// ===============
// 프로퍼티 단축
obj = { x, y }
// 프로퍼티 이름
let obj = {
foo: "bar",
[ "baz" + quux() ]: 42
}
obj[ "baz" + quux() ] = 42;
// 메소드 프로퍼티
obj = {
foo (a, b) {
// ...
},
bar (x, y) {
// ...
},
*quux (x, y) {
// ...
}
}
// 9. 객체와 배열의 매칭
// ====================
// 배열 매칭
var list = [1, 2, 3]
var [a, ,b] = list
console.log(`${a} ${b}`) // 1 3
[b,a] = [a,b]
console.log(`${a} ${b}`) // 3 1
var list = [ 7, 42 ]
var [ a=1, b=2, c=3, d ] = list
console.log( a === 7 )
console.log( b === 42 )
console.log( c === 3 )
console.log( d === undefined )
// 오브젝트 매칭
var { op, lhs, rhs } = getASTNode()
var tmp = getASTNode()
var op = tmp.op
var lhs = tmp.lhs
var rhs = tmp.rhs
var { op: a, lhs: { op: b }, rhs: c } = getASTNode()
var tmp = getASTNode()
var a = tmp.op
var b = tmp.lhs.op
var c = tmp.rhs
// 매칭시 기본값
var obj = { a: 1 }
var list = [ 1 ]
var { a, b = 2 } = obj // a===1, b===2
var [ x, y = 2 ] = list // x===1, y===2
// 매개변수로 사용
function f ([ name, val ]) { console.log(name, val) }
function g ({ name: n, val: v }) { console.log(n, v) }
function h ({ name, val }) { console.log(name, val) }
f([ "bar", 42 ])
g({ name: "foo", val: 7 })
h({ name: "bar", val: 42 })
// 10. 모듈
// ========
// 추출하기와 가져오기
/* lib/math.js */
export function sum (x, y) { return x + y }
export var pi = 3.141593
/* someApp.js */
import * as math from "lib/math"
console.log("2π = " + math.sum(math.pi, math.pi))
/* otherApp.js */
import { sum, pi } from "lib/math"
console.log("2π = " + sum(pi, pi))
// default 와 *(wildcard)
/* lib/mathplusplus.js */
export * from "lib/math"
export var e = 2.71828182846
export default (x) => Math.exp(x)
/* someApp.js */
import exp, { pi, e } from "lib/mathplusplus"
console.log("e^{π} = " + exp(pi))
// 11. 클래스
// ==========
// 클래스 정의
class Shape {
constructor (id, x, y) {
this.id = id
this.move(x, y)
}
move (x, y) {
this.x = x
this.y = y
}
}
// 클래스 상속
class Rectangle extends Shape {
constructor (id, x, y, width, height) {
super(id, x, y)
this.width = width
this.height = height
}
}
class Circle extends Shape {
constructor (id, x, y, radius) {
super(id, x, y)
this.radius = radius
}
}
// 믹스인 [TODO]
var aggregation = (baseClass, ...mixins) => {
let base = class _Combined extends baseClass {
constructor (...args) {
super(...args)
mixins.forEach((mixin) => {
mixin.prototype.initializer.call(this)
})
}
}
let copyProps = (target, source) => {
Object.getOwnPropertyNames(source)
.concat(Object.getOwnPropertySymbols(source))
.forEach((prop) => {
if (prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
return
Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop))
})
}
mixins.forEach((mixin) => {
copyProps(base.prototype, mixin.prototype)
copyProps(base, mixin)
})
return base
}
class Colored {
initializer () { this._color = "white" }
get color () { return this._color }
set color (v) { this._color = v }
}
class ZCoord {
initializer () { this._z = 0 }
get z () { return this._z }
set z (v) { this._z = v }
}
class Shape {
constructor (x, y) { this._x = x; this._y = y }
get x () { return this._x }
set x (v) { this._x = v }
get y () { return this._y }
set y (v) { this._y = v }
}
class Rectangle extends aggregation(Shape, Colored, ZCoord) {}
var rect = new Rectangle(7, 42)
rect.z = 1000
rect.color = "red"
console.log(rect.x, rect.y, rect.z, rect.color)
// 부모 클래스의 메소드 접근
class Shape {
// ...
toString() {
return `Shape(${this.id})`
}
}
class Rectangle extends Shape {
constructor (id, x, y, width, height) {
super(id, x, y)
}
toString() {
return "Rectangle > " + super.toString()
}
}
class Circle extends Shape {
constructor (id, x, y, radius) {
super(id, x, y)
// ...
}
toString() {
return "Circle >" + super.toString()
}
}
// 정적 멤버
class Rectangle extends Shape {
// ...
static defaultRectangle () {
return new Rectangle("default", 0, 0, 100, 100)
}
}
class Circle extends Shape {
// ...
static defaultCircle () {
return new Circle("default", 0, 0, 100)
}
}
var defRectangle = Rectangle.defaultRectangle()
var defCircle = Circle.defaultCircle()
// Getter/Setter
class Rectangle {
constructor (width, height) {
this._width = width
this._height = height
}
set width (width) {
this._width = width
}
get width () {
return this._width
}
set height (height) {
this._height = height
}
get height () {
return this._height
}
get area () {
return this._width * this._height
}
}
var r = new Rectangle(50, 20)
console.log( r.area ) // 1000
// 12. 심볼
// ========
// 심볼
Symbol("foo") !== Symbol("foo")
const foo = Symbol()
const bar = Symbol()
typeof foo === "symbol"
typeof bar === "symbol"
let obj = {}
obj[foo] = "foo"
obj[bar] = "bar"
JSON.stringify(obj) // {}
Object.keys(obj) // []
Object.getOwnPropertyNames(obj) // []
Object.getOwnPropertySymbols(obj) // [ foo, bar ]
// 글로벌 심볼
Symbol.for("app.foo") === Symbol.for("app.foo")
const foo = Symbol.for("app.foo")
const bar = Symbol.for("app.bar")
Symbol.keyFor(foo) === "app.foo"
Symbol.keyFor(bar) === "app.bar"
typeof foo === "symbol"
typeof bar === "symbol"
let obj = {}
obj[foo] = "foo"
obj[bar] = "bar"
JSON.stringify(obj) // {}
Object.keys(obj) // []
Object.getOwnPropertyNames(obj) // []
Object.getOwnPropertySymbols(obj) // [ foo, bar ]
// 13. 이터레이터 [TODO]
// ====================
let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1
return {
next () {
[ pre, cur ] = [cur, pre + cur ]
return { done: false, value: cur }
}
}
}
}
// 14. 제네레이터
// =============
// Generator Function, Iterator Protocol [TODO]
let fibonacci = {
*[Symbol.iterator]() {
let pre = 0, cur = 1
for (;;) {
[ pre, cur ] = [ cur, pre + cur ]
yield cur
}
}
}
for (let n of fibonacci) {
if (n > 1000)
break
console.log(n)
}
// Generator Function, Direct Use [TODO]
function* range (start, end, step) {
while (start < end) {
yield start
start += step
}
}
for (let i of range(0, 10, 2)) {
console.log(i) // 0, 2, 4, 6, 8
}
// Generator Matching [TODO]
let fibonacci = function* (numbers) {
let pre = 0, cur = 1
while (numbers-- > 0) {
[ pre, cur ] = [ cur, pre + cur ]
yield cur
}
}
for (let n of fibonacci(1000))
console.log(n)
let numbers = [ ...fibonacci(1000) ]
let [ n1, n2, n3, ...others ] = fibonacci(1000)
// 14-4. Generator Control-Flow [TODO]
// generic asynchronous control-flow driver
function async (proc, ...params) {
var iterator = proc(...params)
return new Promise((resolve, reject) => {
let loop = (value) => {
let result
try {
result = iterator.next(value)
}
catch (err) {
reject(err)
}
if (result.done)
resolve(result.value)
else if ( typeof result.value === "object"
&& typeof result.value.then === "function")
result.value.then((value) => {
loop(value)
}, (err) => {
reject(err)
})
else
loop(result.value)
}
loop()
})
}
// application-specific asynchronous builder
function makeAsync (text, after) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(text), after)
})
}
// application-specific asynchronous procedure
async(function* (greeting) {
let foo = yield makeAsync("foo", 300)
let bar = yield makeAsync("bar", 200)
let baz = yield makeAsync("baz", 100)
return `${greeting} ${foo} ${bar} ${baz}`
}, "Hello").then((msg) => {
console.log("RESULT:", msg) // "Hello foo bar baz"
})
// Generator Methods
class Clz {
* bar () {
}
}
let Obj = {
* foo () {
}
}
// 15. 맵과 집합
// ============
// 집합
let s = new Set()
s.add("hello").add("goodbyte").add("hellow")
s.size === 2
s.has("hello") === true
for (let key of s.values()) {
console.log(key)
}
// 맵
let m = new Map()
m.set("hello", 42)
m.set(s, 34)
m.get(s) === 34
m.size === 2
for (let [ key, val ] of m.entries()) {
console.log(key + " = " + val)
}
// WeakSet & WeakMap
let isMarked = new WeakSet()
let attachedData = new WeakMap()
export class Node {
constructor (id) {
this.id = id
}
mark () {
isMarked.add(this)
}
unmark () {
isMarked.delete(this)
}
marked () {
return isMarked.has(this)
}
set data (data) {
attachedData.set(this, data)
}
get data () {
return attachedData.get(this)
}
}
let foo = new Node("foo")
JSON.stringify(foo) === '{"id":"foo"}'
foo.mark()
foo.data = "bar"
foo.data === "bar"
JSON.stringify(foo) === '{"id":"foo"}'
isMarked.has(foo) === true
attachedData.has(foo) === true
foo = null
attachedData.has(foo) === false
isMarked.has(foo) === false
// 16. byte 기반 자료 구조
// ======================
class Example {
constructor (buffer = new ArrayBuffer(24)) {
this.buffer = buffer
}
set buffer (buffer) {
this._buffer = buffer
this._id = new Uint32Array (this._buffer, 0, 1)
this._username = new Uint8Array (this._buffer, 4, 16)
this._amountDue = new Float32Array(this._buffer, 20, 1)
}
get buffer () { return this._buffer }
set id (v) { this._id[0] = v }
get id () { return this._id[0] }
set username (v) { this._username[0] = v }
get username () { return this._username[0] }
set amountDue (v) { this._amountDue[0] = v }
get amountDue () { return this._amountDue[0] }
}
let example = new Example()
example.id = 7
example.username = "John Doe"
example.amountDue = 42.0
// 17. 새로운 빌트인 메소드
// ======================
// Object.assign()
var dst = { quux: 0 }
var src1 = { foo: 1, bar: 2 }
var src2 = { foo: 3, baz: 4 }
Object.assign(dst, src1, src2)
console.log(dst) // { quux:0, foo: 3, bar: 2, bax: 4 }
// 배열에서 항목 찾기
[ 1, 3, 4, 2 ].find(x => x > 3) // 4
// 문자열 반복
" ".repeat(4)
"foo".repeat(3)
// 문자열 검색
"hello".startsWith("ello", 1) // true
"hello".endsWith("hell", 4) // true
"hello".includes("ell") // true
"hello".includes("ell", 1) // true
"hello".includes("ell", 2) // false
// 숫자 검사
Number.isNaN(42) === false
Number.isNaN(NaN) === true
Number.isFinite(Infinity) === false
Number.isFinite(-Infinity) === false
Number.isFinite(NaN) === false
Number.isFinite(123) === true
// 숫자 안정성 검사
Number.isSafeInteger(42) === true
Number.isSafeInteger(9007199254740992) === false
// 숫자 비교
console.log(0.1 + 0.2 === 0.3) // false
console.log(Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON) // true
// 반올림/반내림
console.log(Math.trunc(42.7)) // 42
console.log(Math.trunc( 0.1)) // 0
console.log(Math.trunc(-0.1)) // -0
// 숫자 부호
console.log(Math.sign(7)) // 1
console.log(Math.sign(0)) // 0
console.log(Math.sign(-0)) // -0
console.log(Math.sign)-7)) // -1
console.log(Math.sign(NaN)) // NaN
// 18. 프로마이즈 [TODO]
// ====================
// 프로마이즈 사용
function msgAfterTimeout (msg, timeout) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(msg), timeout)
})
}
msgAfterTimeout("", "Foo", 100).then((msg) =>
msgAfterTimeout(msg, "Bar", 200)
).then((msg) => {
console.log(`done after 300ms:${msg}`)
})
// 프로마이즈 조합
function fetchAsync (url, timeout, onData, onError) {
// …
}
let fetchPromised = (url, timeout) => {
return new Promise((resolve, reject) => {
fetchAsync(url, timeout, resolve, reject)
})
}
Promise.all([
fetchPromised("http://backend/foo.txt", 500),
fetchPromised("http://backend/bar.txt", 500),
fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
let [ foo, bar, baz ] = data
console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
console.log(`error: ${err}`)
})
// 19. 메타 프로그래밍
// ==================
// 프록시
let target = {
foo: "Welcome, foo"
}
let proxy = new Proxy(target, {
get (receiver, name) {
return name in receiver ? receiver[name] : `Hello, ${name}`
}
})
proxy.foo === "Welcome, foo"
proxy.world === "Hello, world"
// 리플렉션
let obj = { a: 1 }
Object.defineProperty(obj, "b", { value: 2 })
obj[Symbol("c")] = 3
Reflect.ownKeys(obj) // [ "a", "b", Symbol(c) ]
// 20. 국제화와 지역화
// =================
// Collation
// in German, "ä" sorts with "a"
// in Swedish, "ä" sorts after "z"
var list = [ "ä", "a", "z" ]
var l10nDE = new Intl.Collator("de")
var l10nSV = new Intl.Collator("sv")
l10nDE.compare("ä", "z") === -1
l10nSV.compare("ä", "z") === +1
console.log(list.sort(l10nDE.compare)) // [ "a", "ä", "z" ]
console.log(list.sort(l10nSV.compare)) // [ "a", "z", "ä" ]
// 숫자 형식
var l10nEN = new Intl.NumberFormat("en-US")
var l10nDE = new Intl.NumberFormat("de-DE")
l10nEN.format(1234567.89) === "1,234,567.89"
l10nDE.format(1234567.89) === "1.234.567,89"
// 통화 형식
var l10nUSD = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })
var l10nGBP = new Intl.NumberFormat("en-GB", { style: "currency", currency: "GBP" })
var l10nEUR = new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" })
l10nUSD.format(100200300.40) === "$100,200,300.40"
l10nGBP.format(100200300.40) === "£100,200,300.40"
l10nEUR.format(100200300.40) === "100.200.300,40 €"
// 날짜-시간 형식
var l10nEN = new Intl.DateTimeFormat("en-US")
var l10nDE = new Intl.DateTimeFormat("de-DE")
l10nEN.format(new Date("2015-01-02")) === "1/2/2015"
l10nDE.format(new Date("2015-01-02")) === "2.1.2015"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment