자바스크립트 인터페이스(Interface) 정의
-
자바스크립트 언어상의 고유명사
-
사양의 맞는 값과 연결된 속성키의 셋트
-
어떤 오브젝트라도 인터페이스를 충족시킬 수 있다.
-
하나의 오브젝트는 여러개의 인터페이스를 충족킬 수 있다.
- test라는 키를 가지고 값으로는 문자열 인자를 받아 boolean 값을 리턴하는 함수
// 객체 형태 const testInterface = { test : function(str) { return true; } } // 클래스 형태 const testInterface = class{ test(str){ return true; } }
- test라는 키를 가지고 값으로는 문자열 인자를 받아 boolean 값을 리턴하는 함수
자바스크립트는 덕타이핑으로 구현한 인터페이스?
- 자바스크립트의 인터페이스 덕타이핑을 구현한 프로토콜 같은 것
- testInterface라는 오브젝트를 만들었지만, test라는 함수가 있는지 보장할 수 없다.
런파임 / 컴파일 타임에서 체그할 수 없고도, 상속을 통해서 있는지 오류로 확인한다.
객체를 상관하지 않고, test라는 인터페이스 조건을 만족하면 test인터페이스 구현제로 본다. 이를
덕타이핑
이라고 의미한다 - 가장 중요한 것은 test라는 메소드와 test를 통해서 나오는 값! 다른것은 신경쓰지 않는다.
Iterator Interface란?
- 특징
- next라는 키를 갖고
- 값으로 인자를 받지 않고 iteratorResultObject를 반환하는 함수가 온다
- iteratorResultObject는 value와 done이라는 키를 갖고 잇다
- 이중에 done은 계속 반복할 수 있는지 없는지에 따라 불린값을 반환한다.
const Iterator = { data: [1, 2, 3, 4], next: function () { return { done: this.data.length == 0, value: this.data.pop(), } }, }
- done : 반복 여부, value : 값
Iterable Interface란?
- 특징
- Symbol.iterator라는 키를 갖고
- 값으로 인자를 받지 않고 Iterator Object를 반환하는 함수가 온다
const Iterable = { [Symbol.iterator]: function () { return { next: function () { return { value: 1, done: false } }, } }, }
- Symbol과 ES6의 오브젝트 키에서의 함수
- Symbol은 primitive 타입이며(메모리에서 값이 복사), 유니크한 값
- ES6에서는 오브젝트 내에서 함수를 구현하면 함수의 이름으로 키를 하고 바디를 value로 한다
- ES6의 for-in
- ES6에 숫자 -> 문자열 -> 심볼 순으로 나오면 그 속에서도 순서대로 정렬이 된다.
ES6 Interface 정리
- ES6 이후 부터는 내부에 인터페이스 개념이 도입되서 덕타이핑을 할 수 있는 인터페이스 표준이 있다.
- 만약에 언어에서 인터페이스를 요구하면 인터페이스의 스펙대로 우리가 만든게
Iterable, Iterator
인터페이 - 문자열, 배열에서 이미 구현되어 있다. ES6 이전과는
코어가 다르기 때문에 다르게 동작한다
.
값 vs 문 / 호출지연(연산 / 제어문 / 호출)
- 값 vs 문
- 값은 메모리상에 저장할수 있나 다른 곳에 할당 할수 거 있음.
- 문은 컴파일러(자바스크립트 엔진)에게 힌트를 주어 실행하게 하고 사라진다
- 문 한번 실행 후 메모리에서 사라지고 다시 재연이 불가 복원 불가
- 휘발성의 특징을 가지고 있다.
- 연산지연
// 연산자에 따라 지연 const foo = a || b const bar = a && b
- 제어문 지연
- 원래 컴퓨터는 메모리에 올라온 명령어를 다 실행하여야 하는데
- if/switch 제어문 같은 경우에 실행도중에!!!!
- 지연/점프 시킬수(continue/ breake / else) 다.
- 호출지연
- 코드를 함수바디 안에 가두면 호출되기 전까지 코드는 실행되지 않고 지연된다.
- 함수를 값으로 만든다. 이렇게 원할때 코드를 실행하고 다시 호출할수 있게 만드는 것을 호출지연 예) 값으로 만들거나. 객체의 속성으로 만들어서 호출
- 결론
- 지연이란, 모든 코드를 실행하는 것이 아니라, 부분적으로 읽어 실행하는 것을 말한다.
While 문으로 살펴보는 Iterator
let arr = [1, 2, 3, 4]
while (arr.length > 0) {
// 반복 판단 여부
console.log(arr.pop()) // 반복시 처리할 것
}
const iter = {
[Symbol.iterator]() {
return this
},
arr: [1, 2, 3, 4],
next() {
return {
done: this.arr.length === 0, //반복 판단 여부
value: this.arr.pop(), // 반복시 처리할
}
},
}
-
정의
-
반복 자체를 하지는 않지만, 외부에서 반복을 하려고 할때
-
반복에 필요한 조건과 실행을 미리 준비해 둔 객체
!!! 반복 행위와 반복을 위한 준비를 분리!!!
-
미리 반복에 대한 준비를 해두고, 필요할 때 필요한만큼 반복
-
반복을 재현 할수 잇음
-
-
결론
- 서술적이던 문을 값(함수)으로 대상화한다.
- 문에서는 외부에서 조건을 판단했다면, 값(함수)에서는 내부에서 판단한다.
- 이러한 분리를 통하여 문을 함수로 호출하여 계속해서 호출 할 수있다.
- 단점이라면, 문은 엔진이 자동으로 호출하지만, 함수는 실행기를 만들어주고 호출을 해줘야한다.
객체와 캡슐화
- 정의
- 어떠한 행동에 따라 외부에서 조건을 찾는것이 아니라 내부에서 물어보는것을 객체라고 한다
- 캡슐화
- 외부에서는 내부의 행동(로직)이 보여주지 않고 돈이 있으면 인출하고 없으면 못 인출한다는 것 그 중간과정이 캡슐화(은닉)
- ATM에서 돈을 인출하는 행동이 캡슐화된 것
- 내가 보여주고 싶은 결과만 보여준다 그 안은 신경쓰지마
내부의 사용과 외부의 격리
- 배열과 문자열은 내장객체는 iterator interface의 캡슐화
ES6의 Loop
-
정의
- 지연실행을 기반으로 iterator 객체를 소비하는 형태
- 여기서 구조란 배열,객체가 아니고 Iterable이다(배열 안에는 이터레이터 객체가 있다)
const loop = (iter, f) => { //Iterable이라면 Iterator 얻음 if (typeof iter[Symbol.iterator] === 'function') { iter = iter[Symbol.iterator]() } //IteratorObject가 아니라면 건너뜀 if (typeof iter.next != 'function') return // 쉴드 패턴 while (true) { const v = iter.next() if (v.done) return // 종료처리 f(v.value) } } const iter = { [Symbol.iterator]() { return this }, arr: [1, 2, 3, 4], next() { return { done: this.arr.length === 0, value: this.arr.pop(), } }, } loop(iter, console.log) // 4 3 2 1 // 문자열과 배열은 자체적으로 iterable 인터페이스를 가지고 있다. console.log(typeof ''[Symbol.iterator]) //function console.log(typeof [][Symbol.iterator]) //fuction
-
Array destructuring
const [a, ...b] = iter[Symbol.iterator]() console.log(a, b) // 4, [3,2,1]
-
Spread
const a = [...iter] console.log(a) console.log(a) // [4,3,2,1]
-
Rest parameter
- arguments객체를 쓰는 것보다 rest연산자를 사용하는것이 가독성이 좋다(다른 언어와 비)
- 함수 선언식에서 사용되면 rest operator를 사용!
- 생성자에 배열을 보내고 싶다!!! 그러면 rest operator를 사용한다(call, apply로는 불가능)
const Cls = function (...arg) { this.base = arg } const arr = [1, 2, 3, 4, 5, 6] new Cls(...arr) const test = (...arg) => console.log(arg) test(...iter)
-
for of
- 정의
- of 앞에 벨류값 / of 뒤는 이터레이터 또는 이터레이블 객체 done이 될때까지 계속해서 돌아간다 / 루프에 대한 통제권을 객체가 가지고 잇다
for (const v of iter) { console.log(v) }
- 정의
Generator
-
정의
- 호출하면 Iterator 객체가 나온다(Iteratable은 Iterator 반환)
- yield 통하여 value를 반환한다.
- Coroutine(코루)틴 : 여러번 진입하고(진입 위치가 달라진다 여러번 반환한다) 들어올때 중간부터 들어올수 잇다
const N2 = class{ constructor(max){ this.max = max; } [Symbol.iterator](){ let cursor = 0, max = this.max; return { done:false, next(){ if(cursor > max){ this.done = true; }else{ this.value = cursor * cursor; cursor++; } return this; } }; } }; const generator = function*(max){ let cursor = 0; while(cursor < max){ yield cursor * cursor;cursor++; } }; console.log([...generator(5)]);//[0, 1, 4, 9, 16] for(const v of generator(5)){ console.log(v); }