Til-3 -일급함수, 이터러블/이터레이터

  • 평가

    • 코드가 계산(Evaluation) 되어 값을 만드는 것
  • 일급함수: 함수가 값으로 다뤄질 수 있다

    • 값으로 다룰 수 있다
    • 변수에 담을 수 있다
    • 함수의 인자로 사용가능
    • 함수의 결과로 사용가능
  • const a=10;
    const add10 = a=> a+10
    const r =add10(10);
    console.log(r);
    
    //일급함수 이기에 아래와 같이 사용가능
    var f1= ()=>()=>1;
    
    console.log(f1()); //()=>1
    f1()();   //1
    (f1());   //()=>1
    
  • 고차함수: 함수를 값으로 다루는 함수

    a. 함수를 인자로 받아서 실행하는 함수

const apply1 = f => f(1);
const add2 = a => a + 2;
log(apply1(add2));
log(apply1(a => a - 1));

const times = (f, n) => {
  let i = -1;
  while (++i < n) f(i);
};

times(log, 3);

times(a => log(a + 10), 3);
b. 함수를 만들어 리턴하는 함수 
const addMaker = a => b => a + b;
const add10 = addMaker(10);
log(add10(5));
log(add10(10));
  • es6에서의 리스트 순회(for of , for in)
const list = [1, 2, 3];
for (var i = 0; i < list.length; i++) {
  // log(list[i]);
}
const str = 'abc';
for (var i = 0; i < str.length; i++) {
  // log(str[i]);
}
for (const a of list) {
  // log(a);
}
for (const a of str) {
  // log(a);
}
  • 이터러블/이터레이터 프로토콜

    a. 이터러블: 이터레이터를 리턴하는 Symbol.iterator 를 가진 값 b. 이터레이터: { value, done } 객체를 리턴하는 next() 를 가진 값 c. 이터러블/이터레이터 프로토콜: 이터러블을 for...of, 전개 연산자 등과 함께 동작하도록한 규약

### Array를 통해 알아보기

<script>
log('Arr -----------');
  const arr= [1, 2, 3];
  let iter1=arr[Symbol.iterator](); //arr: 이터러블, iter1: 이터레이터
  for (const a of iter1)log(a);     //iter1.next(); 입력할때마다 다음값 출력
</script>

### Set을 통해 알아보기

<script>
log('Set -----------');
  const set= new Set([1, 2, 3]);
  for (const a of set)log(a);
</script>

### Map을 통해 알아보기

<script>
log('Map -----------');
  const map= new Map([['a', 1], ['b', 2], ['c', 3]]);
  for (const a of map.keys())log(a); //키 정보만 가져옴
  for (const a of map.values())log(a);
  for (const a of map.entries())log(a);
console.clear();
</script>

  • 사용자 정의 이터러블/이터레이터 구현
const iterable = {
    [Symbol.iterator]() { **//동적인 값을 key로 사용하기 위한 메소드 생성방법(이해X)**
        let i = 3;
        return {
            next(){
                return i==0? {done:true}: {value:i--, done:false}
            },
					  **[Symbol.iterator](){return this}**
						//이걸로 인해 iterator for of 문이 가능하고 next 후 중간부터도 시작 가능함
        }
    }
}
var iterator= iterable[Symbol.iterator](); //메소드 실행
console.log(iterator.next()); //{ value: 3, done: false }
console.1log(iterator.next()); //{ value: 2, done: false }
console.log(iterator.next()); //{ value: 1, done: false }

for(a of iterable){
    console.log(a); //3,2,1
}
for(a of iterator){ // [Symbol.iterator](){return this} 때문에 실행 가능
    console.log(a); //3,2,1
}

//기존 iterable은 next를 사용해서 중간부터 시작할 수 있음
const arr2= [1,2,3];
let iter2= arr2[Symbol.iterator]();
iter2.next(); //한번 호출 했음으로 2,3 출력
for(a of iter2){ 
    console.log(a);
}
  • 최근 array, map, set 내장 객체 뿐만 아니라 오픈 소스및 브라우저 web api 에서도 이터러블/이터레이터를 사용 할 수 있음
for(a of document.querySelectorAll('*')){
    console.log(a)
};
  • 전개연산자 역시 이터러블/이터레이터를 이용한 함수
console.clear();
  const a = [1, 2];
  // a[Symbol.iterator] = null; //주석풀면 전개연산자 사용 불가
  log([...a, ...arr, ...set, ...map.keys()]);
  • 제너레이터와 이터레이터

    • 제너레이터: well-formed 이터레이터를 리턴하는 함수
    • 자바스크립트에서 iterator이면 for of 로 순회 할 수 있다
    • 즉 제너레이터 함수 내부 문장을 사용하여 어느 값이나 상태를 순회 할 수 있다
    function *gen(){
        yield 1;
        yield 2;
        yield 3;
        return 100;
    }
    let iter =gen();
    console.log(iter == iter[Symbol.iterator]()); //well-formed이터레이터
    console.log(iter.next());
    console.log(iter.next());
    console.log(iter.next());
    console.log(iter.next());
    //{ value: 1, done: false }
    //{ value: 2, done: false }
    //{ value: 3, done: false }
    **//{ value: 100, done: true }**
    for(let a of gen()) console.log(a); //1,2,3 (리턴값은 안나옴)
    
  • 제너레이터 실습

function *odd(l){
    for(let i=0;i<l;i++){
        if(i%2) yield i;
    }

}
let iter = odd(10);
for(a of iter){
    console.log(a);
}

//무한히 실행되도 next로 평가받는 시점까지의 수만 나옴
function *infinity(i=0){
    while(true) yield i++
}

let iter2= infinity();
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());

//
function *limit(l, iter){
    for(const a of iter) {
        yield a; //next() 할때마다 값이 나옴
        if (a == l) return;
    }
}

let iter4= limit(4,[1,2,3,4,5,6]); //까지만 출력
for(let a of iter4){
    console.log(a);
}

//limit와 infinity를 이용해 아래와 같이 변경 가능
function *odd(l){
    **for(const i of limit(l,infinity(1))) {**
        if (i % 2) yield i;
        if(i==l) return;
    }
}
  • for...of, 전개 연산자, 구조 분해, 나머지 연산자
    • 이터레이터 활용
console.log(...odd(10)); //1~9
console.log([...odd(10), ...odd(20)]); //[1~9, 1~19]

const [head , ...tail] = odd(5);
console.log(head); //1
console.log(tail); //[3,5]

댓글을 작성해보세요.

채널톡 아이콘