Jun 개발노트

코드스피치 강의 ES6+ 3회차 정리

July 23, 2020

자바스크립트 인터페이스(Interface) 정의

  1. 자바스크립트 언어상의 고유명사
  2. 사양의 맞는 값과 연결된 속성키의 셋트
  3. 어떤 오브젝트라도 인터페이스를 충족시킬 수 있다.
  4. 하나의 오브젝트는 여러개의 인터페이스를 충족킬 수 있다.

    • test라는 키를 가지고 값으로는 문자열 인자를 받아 boolean 값을 리턴하는 함수

      // 객체 형태
      const testInterface = {
          test : function(str) {
                   return true;
                 }
      }
      
      // 클래스 형태     
      const testInterface = class{
         test(str){
           return true;
         } 
       }   

자바스크립트는 덕타이핑으로 구현한 인터페이스?

  1. 자바스크립트의 인터페이스 덕타이핑을 구현한 프로토콜 같은 것
  2. testInterface라는 오브젝트를 만들었지만, test라는 함수가 있는지 보장할 수 없다. 런파임 / 컴파일 타임에서 체그할 수 없고도, 상속을 통해서 있는지 오류로 확인한다. 객체를 상관하지 않고, test라는 인터페이스 조건을 만족하면 test인터페이스 구현제로 본다. 이를 덕타이핑이라고 의미한다
  3. 가장 중요한 것은 test라는 메소드와 test를 통해서 나오는 값! 다른것은 신경쓰지 않는다.

Iterator Interface란?

  1. 특징

    • 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()
                     }
                   }      
        }   
  2. done : 반복 여부, value : 값

Iterable Interface란?

  1. 특징

    • Symbol.iterator라는 키를 갖고
    • 값으로 인자를 받지 않고 Iterator Object를 반환하는 함수가 온다

       const Iterable = 
         {
             [Symbol.iterator]: function(){
                     return {
                       next: function(){
                          return {value:1, done:false}
                        }
                     }
             }      
        }   
  2. Symbol과 ES6의 오브젝트 키에서의 함수

    • Symbol은 primitive 타입이며(메모리에서 값이 복사), 유니크한 값
    • ES6에서는 오브젝트 내에서 함수를 구현하면 함수의 이름으로 키를 하고 바디를 value로 한다
  3. ES6의 for-in

    • ES6에 숫자 -> 문자열 -> 심볼 순으로 나오면 그 속에서도 순서대로 정렬이 된다.

ES6 Interface 정리

  1. ES6 이후 부터는 내부에 인터페이스 개념이 도입되서 덕타이핑을 할 수 있는 인터페이스 표준이 있다.
  2. 만약에 언어에서 인터페이스를 요구하면 인터페이스의 스펙대로 우리가 만든게 Iterable, Iterator 인터페이
  3. 문자열, 배열에서 이미 구현되어 있다. ES6 이전과는 코어가 다르기 때문에 다르게 동작한다.

값 vs 문 / 호출지연(연산 / 제어문 / 호출)

  1. 값 vs 문

    • 값은 메모리상에 저장할수 있나 다른 곳에 할당 할수 거 있음.
    • 문은 컴파일러(자바스크립트 엔진)에게 힌트를 주어 실행하게 하고 사라진다

      • 문 한번 실행 후 메모리에서 사라지고 다시 재연이 불가 복원 불가
      • 휘발성의 특징을 가지고 있다.
  2. 연산지연

     // 연산자에 따라 지연
     const foo = a || b;
     const bar = a && b;
  3. 제어문 지연

    • 원래 컴퓨터는 메모리에 올라온 명령어를 다 실행하여야 하는데
    • if/switch 제어문 같은 경우에 실행도중에!!!!
    • 지연/점프 시킬수(continue/ breake / else) 다.
  4. 호출지연

    • 코드를 함수바디 안에 가두면 호출되기 전까지 코드는 실행되지 않고 지연된다.
    • 함수를 값으로 만든다. 이렇게 원할때 코드를 실행하고 다시 호출할수 있게 만드는 것을 호출지연 예) 값으로 만들거나. 객체의 속성으로 만들어서 호출
  5. 결론

    • 지연이란, 모든 코드를 실행하는 것이 아니라, 부분적으로 읽어 실행하는 것을 말한다.

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() // 반복시 처리할 
        }
      }
    }
  1. 정의

    • 반복 자체를 하지는 않지만, 외부에서 반복을 하려고 할때
    • 반복에 필요한 조건과 실행을 미리 준비해 둔 객체

      !!! 반복 행위와 반복을 위한 준비를 분리!!!

    • 미리 반복에 대한 준비를 해두고, 필요할 때 필요한만큼 반복
    • 반복을 재현 할수 잇음
  2. 결론

    • 서술적이던 문을 값(함수)으로 대상화한다.
    • 문에서는 외부에서 조건을 판단했다면, 값(함수)에서는 내부에서 판단한다.
    • 이러한 분리를 통하여 문을 함수로 호출하여 계속해서 호출 할 수있다.
    • 단점이라면, 문은 엔진이 자동으로 호출하지만, 함수는 실행기를 만들어주고 호출을 해줘야한다.

객체와 캡슐화

  1. 정의

    • 어떠한 행동에 따라 외부에서 조건을 찾는것이 아니라 내부에서 물어보는것을 객체라고 한다
  2. 캡슐화

    • 외부에서는 내부의 행동(로직)이 보여주지 않고 돈이 있으면 인출하고 없으면 못 인출한다는 것 그 중간과정이 캡슐화(은닉)
    • ATM에서 돈을 인출하는 행동이 캡슐화된 것
    • 내가 보여주고 싶은 결과만 보여준다 그 안은 신경쓰지마 내부의 사용과 외부의 격리
  3. 배열과 문자열은 내장객체는 iterator interface의 캡슐화

ES6의 Loop

  1. 정의

    • 지연실행을 기반으로 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
  2. Array destructuring

    const [a, ...b] = iter[Symbol.iterator]();
    console.log(a, b) // 4, [3,2,1]
  3. Spread

    const a = [...iter];console.log(a);
    console.log(a) // [4,3,2,1]
  4. 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);
  5. for of

    • 정의

      • of 앞에 벨류값 / of 뒤는 이터레이터 또는 이터레이블 객체 done이 될때까지 계속해서 돌아간다 / 루프에 대한 통제권을 객체가 가지고 잇다

        for(const v of iter){
        console.log(v);
        } 

Generator

  1. 정의

    • 호출하면 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);
          }

Written by Junho You 배운것을 기록하자