DevFest WebTech CodeLab

DevFest WebTech CodeLab

ES6 & ES7

classes

  • JS에 새로운 Object Oriented Pattern을 제시한 건 아님에 주의
    • 사실 함수
    • 그러나 Function declaration처럼 hoisted되지 않음
어떻게 사용할 수 있나요?
class 선언
1
2
3
4
5
6
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
class 표현식
  • 이름을 가질 수도 있고, 갖지 않을 수도 있다

  • 이름을 가진 class 표현식의 이름은 클래스의 body에 대해 local scope에 한해 유효

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // unnamed
    let Rectangle = class {
    constructor(height, width) {
    this.height = height;
    this.width = width;
    }
    };

    console.log(Rectangle.name);
    //output : "Rectangle"

    // named
    let Rectangle = class Rectangle2 {
    constructor(height, width) {
    this.height = height;
    this.width = width;
    }
    };

    console.log(Rectangle.name);
    //output: "Rectangle2"
예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class nameOfClass extends existingClass {
constructor() {
// ...
}

someFunction() {
// ...
}

get someVariable() {
// ...
}

set someVariable(variable) {
// ...
}

static someStaticFunction() {
// ...
}
}
  • new 생성자가 하나의 객체를 만드는 것이 아니라 연결된 무언가를 만드는 것이라 이해해야 한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class GDGEvent {
constructor(eventName, eventDate) {
this.eventName = eventName
this.eventDate = eventDate
}

updateEvent(eventName, eventDate) {
// ...
}
}

class GDGWebTechEvent extends GDGEvent {
constructor(eventName, eventDate, focusingTopic) {
super(eventName, eventDate)
this.focusingTopic = focusingTopic
this.eventPlace = GDGWebTechEvent.defaultEventPlace()
}

updateEvent(eventName, eventDate, focusingTopic) {
// do something with focusingTopic
super.updateEvent(eventName, eventDate)
}

get eventInformation() {
return `${this.eventName} will be held at ${this.eventDate} focusing on ${this.focusingTopic}`
}

static defaultEventPlace() {
return 'Google for Startups located in Seoul, Korea'
}
}

const devFestWebTech2019 = new GDGWebTechEvent(
'DevFest WebTech', '21 Nov 2019', 'web technologies'
)
console.log(devFestWebTech2019.eventInformation)
// 'DevFest WebTech will be held at 21 Nov 2019 focusing on web technologies'

array API

Array.from()

  • 유사 배열 객체나 순회 가능 객체를 복사해 새로운 배열을 만드는 메서드
    • 유사 배열 객체
      • length 속성과 인덱싱된 요소를 가진 객체
    • 순회 가능 객체
      • map, set 등 객체의 요소를 얻을 수 있는 객체
1
2
Array.from('foo'); 
// ["f", "o", "o"]
1
2
3
const s = new Set(['foo', window]); 
Array.from(s);
// ["foo", window]

Array.of()

인자의 수나 유형에 관계없이 가변 인자를 갖는 새 Array 인스턴스를 생성

1
2
Array.of(7);       // [7] 
Array.of(1, 2, 3); // [1, 2, 3]

Array.fill()

1
2
3
4
5
6
7
8
9
10
11
12
13
const array1 = [1, 2, 3, 4];

// 2번 째 인덱스부터 4-1번째 인덱스까지 0으로 채우기
console.log(array1.fill(0, 2, 4));
// expected output: [1, 2, 0, 0]

// 1번 째 인덱스부터 5로 채우기
console.log(array1.fill(5, 1));
// expected output: [1, 5, 5, 5]

// 모든 배열을 6으로 채우기
console.log(array1.fill(6));
// expected output: [6, 6, 6, 6]

Array.includes

기존의 indexOf 는 특정 요소가 있는지 검사하고 0 또는 1을 반환했지만, includes는 동일하게 요소를 검사하고 boolean을 반환

1
2
[1, 2, 3].includes(-1)                   // false
[1, 2, 3].includes(1) // true

**

수를 제곱

1
2
3
4
5
// 5의 세제곱을 구할때 기존의 방법
Math.pow(5, 3)

// 이제는 operand ** operand 이렇게 사용할 수 있어요
5 ** 3 // 125

ES8 & ES9

Object entries, values

Objectenumerable property pair를 꺼내오거나 value만 배열로 꺼내올 수 있다

1
2
3
4
5
6
7
8
9
10
11
12
13
// Object.entries()
const obj = { eventName: 'DevFest WebTech', eventPlace: 'Google for Startups' }
console.log(Object.entries(obj))
// [ ['eventName', 'DevFest WebTech'], ['eventPlace', 'Google for Startups'] ]

// Object.values()
const obj = { foo: 'foo', bar: [100, 200], baz: 55 }
console.log(Object.values(obj))
// ['foo', [100, 200], 55 ]

const myStr = 'Lufthansa'
console.log(Object.values(myStr))
// ["L", "u", "f", "t", "h", "a", "n", "s", "a"]

ES10

Array flat & flatMap

Array에 배열의 배열을 flat 시킬 수 있는 conversion helper가 추가

1
2
3
4
5
6
7
8
9
10
11
// Array flat
let arr = ['a', 'b', ['c', 'd']]
let flattened = arr.flat()
console.log(flattened) // ["a", "b", "c", "d"]

// Array flatMap
const arr = [4.25, 19.99, 25.5]
console.log(arr.map((value) => [Math.round(value)]))
// [[4], [20], [26]]
console.log(arr.flatMap((value) => [Math.round(value)]))
// [4, 20, 26]

Object fromEntries

Objectentries()가 리터럴 객체의 property pair를 배열로 가져올 수 있는 반면, 반대로 그 배열로 리터럴 객체로 만들 수 있는 함수

1
2
3
4
const myArray = [['one', 1], ['two', 2], ['three', 3]]
const obj = Object.fromEntries(myArray)

console.log(obj) // {one: 1, two: 2, three: 3}

RxJS의 주요 개념

Observable

Observable

시간을 축으로 연속적인 데이터를 저장하고 있는 객체

검색 기능을 만든다고 가정할 때, input에 유저가 검색어를 입력하기 시작하면 입력한 순서대로(, , , ) 데이터가 넘어간다. 해당 객체는 이렇게 시간순으로 오는 데이터를 의미

Operator

Observable이 변화하는 데이터 흐름 사이특정한 작업을 해야만 할 때 사용

Observable을 만들어내기도 함.

OperatorObservable을 받아 어떤 작업을 하고 새로운 Observable을 넘기고, 또 다른 다음 Operator가 받는 식

Observer

가공된 데이터를 활용하는 역할

next, error, complete 함수를 프로퍼티로 갖는 객체

1
observableInstance.subscribe(Observer)

이렇게 subscribe 함수 안에 넣어주면 데이터를 꺼냄

Subscription

데이터를 활용하지 않아 사용한 메모리 자원을 다시 반환해야 할 때 사용할 객체

1
subscription.unsubscribe()

Observable 인스턴스의 subscribe 함수는 subscription 객체를 반환

예제

함수들은 rxjs/operator 안에 있다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const inputStream = fromEvent(searchInput, 'input')
// fromEvent
// DOM EventTarget과 이 타겟에서 데이터로 삼을 이벤트명을 인자로 받고
// 그 이벤트명의 이벤트를 데이터 스트림으로 표현하는 Observable 객체를 반환
.pipe(
// 새로운 Observable 객체를 반환
// 데이터 스트림이 어떻게 변화하는지를 모두 표현하고 있는 새로운 Observable 객체가 할당
// 데이터가 흐르기 시작
map((event) => event.target.value),
debounceTime(1000),
// 1초 동안 아무런 이벤트가 발생하지 않았을 때, 최종적으로 발생한 이벤트만을 대상으로 호출
distinctUntilChanged(),
// 만약 같은 데이터가 들어왔다면
// 해당 이벤트를 무시하며 흐름을 중지한다
tap(() => recipeList.innerHTML = '<h3>Loading...</h3>'),
// 도착한 데이터에 어떠한 변경도 하지 않음
// 데이터와 무관한 활동을 해야할 때 사용
switchMap((inputValue) =>
// 옵져버블 안에 있는 값을 꺼내야 할 경우
// 중첩 파이프라인의 값을 가져옴
// 팬딩된 요청에 대해서는 무시. 왜냐하면 유저 입장에서는 첫 요청보단 두 번째 요청을 먼저 실행하길 원하므로
// 파이프라인 두 개를 합치는 역할

// 프로미스를 리턴하지 않음
ajax(`${apiEndPoint}?f=${inputValue}`, { method: 'GET' })
.pipe(
// 새로운 파이프 라인 시작
map(({ response }) => response ? response.meals : []),
),
),
)
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
inputStream.subscribe({
next: (meals) => {
// 받고 나서 할 일
recipeList.innerHTML = meals
.map((meal) => new Meal(meal))
.map((mealInstance) => mealInstance.renderToString())
.join('')
},
error: () => {
// 데이터 스트림 과정에 에러가 있을때 호출
recipeList.innerHTML = '<h3>An error has occurred when fetching data...</h3>'
},
})
// complete는 Observable의 구독이 완료되었을때 호출