JavaScirpt/basic

[JavaScript] 문법 기초(for ~of, for ~in, forEach, 함수, 커링, 펼침 연산자, 나머지 파라미터, 화살표 함수, 고차함수, 생성자 함수)

Tree_Park 2020. 12. 20. 19:38
728x90

목차

    for ~ of 문
    • 여러 개의 요소를 가지는 배열, 문자열, 맵, 셋 등의 자료 구조의 경우에서 모든 요소에 대한 조건 체크나, 순환하면서 요소의 값을 갱신하는 작업을 하는 경우가 있다

    • for문이 아닌, 조금 더 간결하고 안전한 for ~ of 문을 사용하여 작성할 수 있다.

    • for ~ of문은 배열, 문자열, 맵, 셋 객체에서 사용 가능

      • 규격  명세에서 [Symbol.iterator] 속성이 있는 객체만 사용 가능

    • 일반 객체의 속성에 접근하기 위해서는 for ~ in을 사용

     

    • for ~ of 문의 구조

    for(let 요소변수이름 of 대상) {
    // 반복 실행문
    }
    
    let people = {
    {name: ‘name11’, age: 12},
    {name: ‘name12’, age: 13},
    };
    for(let person of people) {
    console.log(`name: ${person.name}`, age: ${person.age}`);
    }
    //name: name11, age: 12
    //name: name12, age: 13
    • “반복 실행 건을 체크하는 괄호안의 구문은 people 배열의(of)에 있는 요소 한 개(person)씩을 가져와 반복 실행문에 대입”

    • for문과의 차이는 괄호 안의 조건식이 루프를 도는 조건 체크가 필요 없이 간결해진 점과

    • 반복 실행문에 인덱스가 없다는 점.

      • 때문에 인덱스의 표기 실수로 인한 에러가 발생하지 않고, 객체의 속성이나 요소에 대해 알아보기 쉽게 접근 가능

     

    • for, for ~ of 반복문에서 배열이나 객체의 요소 삭제 작업을 하면 에러를 발생시킬 수 있다.

    • 요소 삭제하는 방법에 따라서, 배열 요소는 삭제되었지만 배열 길이는 줄지 않는 경우도 있기 때문에, 반복문 안에서는 순환을 하고 있는 배열이나 객체의 요소를 삭제하는 것은 피해야 한다.

     

     

    for ~ in 문
    • 객체의 전체 속성 키를 나열하는데 사용하는 반복문

    • 배열, 문자열, 맵, 셋 객체에 사용할 경우 배열의 인덱스 값만 반환된다.

    • 기본 구조

    for(let 속성 in 객체) {
    // 속성 처리 구문
    }
    
    let person = {name: ‘name1’, age: 1};
    for(let prop in person) {
    console.log(`prop: ${prop}, value: ${person[prop]}`);
    }
    //prop: name, value: name1
    //prop: age, value: 1
    



     

    forEach 구문
    • 범용인 기본 순환 구문은 아니며 배열 전용의 메서드. 배열의 모든 요소를 순환하는 메서드로, 콜백함수를 이용해 배열 요소에 다양한 처리 가능

    • 배열 요소 순환 처리에 필요한 요소 객체와 인덱스 값을 모두 인자로 받을 수 있다.

    • 구조

    배열.forEach(function (요소[, 인덱스]) {
    // 요소 처리 실행문
    });
    • 인덱스는 생략 가능. 요소가 첫 번째 파라미터로 온다는 점에 유의
      for ~ of 처럼 간단하게 코드를 작성 가능하지만, 기본적으로 배열의 메서드이기 때문에 배열에만 사용 가능

    let people = [
    {name: ‘name1’, age: 1},
    {name: ‘name2’, age: 2}
    ];
    people.forEach(function(person, idx) {
    console.log(`name: ${person.name}, age:${person.age});
    });
    //name:name1, age:1
    //name:name2, age:2
    
    

     

     

    주의
    • 대부분의 개발 언어에서 순환문, 반복문을 중간에 빠져나가는 중단문 사용을 권장하지 않는다. (속도 저하와 프로그램 로직을 건너뛰는 것으로 인한 가독성 저하)

    • 실제로 성능적인 저하는 미미하지만, 프로그램 로직의 흐름을 이해하고 파악하는데 심각한 저하

     

     

    자바스크립트 함수의 이해
    • 자바스크립트는 함수형 언어

    • 구현하는 기능들은 기본적으로 모든 함수를 통해 구현

    • 함수의 구조

    function 함수이름 (파라미터) {
    // 실행영역
    }

     

    • 함수의 영역

     

    키워드

    설명

    function

    함수 임을 표시하는 고정 키워드

    함수이름

    함수를 호출할 때 사용하는 명칭. (함수 이름 없이 사용하는 익명 함수도 있기에 경우에 따라 필수는 아니다.)

    함수 이름은 이름을 정하는 일정한 규칙에 따라 사용하는 것이 좋다.

    함수 이름은 함수를 선언하는 방식에 따라 function 뒤에 오거나 function 앞에 대입 변수명으로 올 수 있다. 

    파라미터

    인자, 매개변수
    괄호로 감싸 표현하며, 파라미터가 없을 경우 ()만으로 표시하고, 괄호는 생략 불가
    함수 안의 실행 영역에 전달할 값이 있을 경우 파라미터를 이용해 값을 넘기게 된다.
    ES6에서 추가된 화살표 함수에서 예외적으로 괄호를 생략 가능한 경우가 있다.
    가능하면 전역 변수 사용을 피하고, 함수 안에서 필요로 하는 데이터는 파라미터를 통해 전달한다는 기준을 가지고 코딩

    실행 영역

    원하는 값을 얻기 위해, 화면에 표시하기 위해 자바스크립트 코드를 작성하는 영역
    함수의 실행 결과 값을 반환하기 위해
    return 결과 값;
    같은 반환 코드를 추가 가능.
    return이 없으면 “undefined”를 리턴

     

     

    함수 정의 방법
    • 함수 선언문 형태로 만드는 방법

    function myFunc(param) {
    console.log(parma + ‘ run!’);
    }
      • 함수 리터럴을 사용해 변수에 함수를 할당하는 방식

      • 리터럴은 변수에 값이나 객체, 함수 등을 대입해 변수 자체가 대상을 가리키도록 하는 것

     

    • 함수 표현식으로 만드는 방법

    const myFunc2 = function(param) {
    console.log(param + ‘run!’);
    }
    • 함수 사용 방법은 둘다 동일

     

     

    함수 파라미터의 이해
    • 파라미터와 인자

      • 함수가 넘겨 받는 값 들을 담기 위한 함수 내부에서 사용하는 변수

      • 파라미터 개수는 기본적으로 함수 선언 시점에 정해지지만, 나머지 파라미터(Rest Parameter)를 사용할 경우 추가적인 가변 개수를 사용 가능하여 파라미터 개수에 제한을 없앨 수 있다

      • 자바스크립트는 파라미터 개수와 인자 개수가 일치하지 않아도 에러가 발생하지 않는다.

      • 파라미터 개수보다 인자 개수가 많을 경우 파라미터 개수 만큼만 값이 전달

      • 추가의 인자 값은 함수 내부의 독특한 객체인 “arguments”를 통해 접근 가능

      • 파라미터 개수보다 인자 개수가 적을 경우 남는 파라미터는 “undefined”가 전달

      • 인자 값에 대한 사전 체크를 하지 않을 경우 인자와 파라미터 개수 불일치 시 내부 코드 실행 중 에러가 발생할 수 있다.

      • 이럴 경우를 대비해 기본 파라미터 값을 정해 줌으로써 인자 값이 전달되지 않으면, 기본 값이 사용되도록 하여 에러 발생 가능성을 낮출 수 있다.

      • 파라미터 : 함수 정의 시점에 정의하는 변수

      • 인자 : 실제 함수를 호출하는 시점에 함수 호출과 함께 함수로 넘어가는 값들

     

    • 기본파라미터(Default Parameter)

      • ES6 추가 기능, 함수 정의할 때 파라미터 기본값 설정

      • 파라미터 값에 대한 사전 체크를 해야 하는 번거로움이 사라지고, 에러가 없으면서도 최적화된 코드 작성 가능

    function sum(a=0, b=0) {
    return a+b;
    }
    console.log(sum(4,5)); // 9
    console.log(sum()); // 0

     

    • 나머지 파라미터(Rest Parameter)

      • 파라미터 개수를 가변으로 사용할 수 있도록 해주는 기능

      • 함수의 확장성을 높여주는 ES6에서 추가된 기능

      • 맨 마지막 파라미터, 또는 단독 파라미터 변수 명 앞에 붙여서 점 3개(...)를 표시하면 해당 파라미터는 나머지 파라미터가 된다.

      • 나머지 파라미터만 파라미터로 사용한 경우 파라미터의 최소 개수는 0개부터 N개가 된다.

     

    • function myFunc(...args) { }
      // 최소 2개의 파라미터는 필수 이고, 추가의 파라미터는 선택적인 파라미터
      function myFunc2(a, b, ..args) { }
      // 나머지 파라미터는 배열 객체로 넘어오기 때문에 순환 구문으로 나머지
      //파라미터들에 대한 처리를 손쉽게 처리 가능

    function sum(a,b, ...args) {
    let result = a+b;
    args.forEach(function(arg) {
    result += arg;
    });
    return result;
    }

     

    • arguments 객체

      • 함수 안에서만 기본으로 사용할 수 있는 자바스크립트의 독특한 객체

      • 함수 런타임 시점에 자동으로 생성되는 객체이며, 함수 코드 및 파라미터와는 무관하게 자동 생성

     

      • 함수 실행 시 함수로 전달된 실제 인자들의 정보를 담고 있는 객체. 모든 파라미터에 대한 정보를 담고 있다.

     

      • 함수 선언에서 파라미터로 정의한 변수 개수보다 실제 함수 호출 시 전달하는 인자의 개수가 다를 수 있는 자바스크립트의 특성을 고려하여 만들어진 객체.

      • 일반적이지 않지만, 예외적으로 모듈을 구현할 때나, 넘겨받은 파라미터의 개수가 유동적인 저 수준 라이브러리를 작성할 때만 제한적으로 사용

     

      • 나머지 파라미터를 사용한 경우 추가의 인자 값은 나머지 파라미터를 통해 접근할 수도, arguments 객체를 통해 접근할 수도 있다.

    function sum() {
    let result = 0;
    for(let i=0; i<arguments.length; i++) {
    result += arguments[i];
    }
    return result;
    }
    console.log(sum(1,2,3,4,5)); // 15

     

     

    커링(Curring) 함수의 기초
    • 한 번에 하나의 인수를 받는 함수 : 커링 or 파샬 어플리케이션(Partial application)

    • 커링은 복잡한 파라미터를 넘겨서 복잡한 처리를 하는 하나의 자바스크립트 함수를
      단순하고 읽기 쉬운 여러 개의 나누어진 부분으로 만드는 기법

     

    • 메서드의 실행 구조를 단순화하여 읽기 쉽고, 실행 구조가 명확하게 읽혀지는 코드를 작성 가능하도록 하는 일반 개발 방법 중 하나

    function orderSet(burger, beverage) {
    console.log(`세트: ${burger}, ${beverage}) 
    }
    orderSet(“치즈버거”, “콜라”); // 세트: 치즈버거, 콜라
    
    // 커링 해체
    function orderSet2(burger) {
    return function(beverage) {
    console.log(“세트: ${burger}, “${beverage}
    }
    
    let order = orderSet(“치즈버거); // return function(beverage)
    order(“콜라”); // 세트: 치즈버거, 콜라
    order(“커피”); // 세트 : 치즈버거, 커피
    
    orderSet(“치즈버거”)(“환타”); // 세트: 치즈버거, 환타
    • 위 예제처럼 2개의 인자를 체인 형태로 넘겨 커링을 실행할 수도 있다.

    • 커링은 이런 방식으로 n개의 파라미터를 n차 뎁스(Depth)를 가진 함수로 분리하는 것

     

    • 커링의 장점

      • 중간 단계까지만 실행한 결과를 변수로 받아 다음 파라미터를 다양하게 확장 가능하기 때문

      • 중간 단계에서 여러 개의 인자를 넘겨 다양한 결과 생성 가능

    • 파라미터의 개수가 많을 경우 코드 재활용성을 극단적으로 높일 수 있다.

    function orderSet(burger) {
    	return function orderBeverage(beverage) {
    		return function orderSide(side) {
    			return function orderKetchup(yn) {
    				console.log(`세트: ${burger}, ${beverage}, ${side}`);
    			}
    		}
    	}
    }
    
    • 이런 커링이 있을 경우
      let order = orderSet(“치즈버거”)(“콜라”);

      이렇게 반환을 받으면 치즈버거와 콜라만 선택되고 나머지가 선택되지 않으면 중간 함수를 변수에 반환 받아 추가 선택이 가능

      order(“프레치후라이”)(“y”);

    • 위처럼 추가 파라미터를 넘겨 완성한 결과를 출력 가능.

    • 재활용성은 극단적으로 높아지지만, 함수들이 중첩되면서 복잡도만 더 가중하는 것 같다면 화살표 함수를 사용한 다음 예가 도움이 된다.

    const orderSet = burger => beverage => side =>  {
    		console.log(`set: ${burger}, ${beverage}, ${side}`);
    	} 
    

     

     

    펼침 연산자(spread operator), 전개 구문, 나머지 파라미터
    • 펼침 연산자

      • 변수 명 앞에 마침표 3개(...) 표시

      • 펼침 연산자는 적용한 객체의 개별 속성 요소를 펼쳐 각각의 개별 요소, 속성이 순서대로 적용되도록 한다.

     

      • 배열 변수 명 앞에 펼침 연산자를 표시해서 함수 인자로 넘기면 배열의 요소 들이 파라미터 순서에 맞춰 하나씩 자동 적용

      • 전개 구문만으로 함수 파라미터를 적용하면 파라미터가 오는 순서에 구애받지 않고 파라미터를 사용할 수 있다

    let calc = function(x, y, ...restparams) {
    return x+y+restparams.reduce(function(sum, param) return sum+param;));
    }
    let arr = [0,1];
    console.log(calc(-1, ...arr, 2, …[3])); // 배열로 넘어가는 인자들을 펼쳐 
    // 파라미터 순서로 적용 (5)
    
    let arr2 = [1,2,3,4,5,6];
    console.log(calc(...arr2)); // (21)
    console.log(calc(null, ...arg2)); // null, 1, 2, 3, 4, 5, 6이 파라미터에 적용
    // (21)
    

     

    • 함수 메서드를 정의할 때 파라미터에 펼침 연산자를 붙여 정의하면 나머지 파라미터가 된다.
      나머지 파라미터는 함수에 가변 파라미터 개수를 구현해주는 선언 방식으로, 맨 마지막 위치의 파라미터에만 사용 가능

    • 인자로 넘기는 변수에는 인자 위치에 상관 없이 펼침연산자를 사용 가능하지만 함수를 정의할 때는 마지막 파라미터만 펼침 연산자를 사용 가능하다는 점을 주의

    • var arr = [1,2,3];
      var arr2 = [...arr]; // 배열의 복사

    • 배열을 합치는 배열 메서드인 concat() 메서드보다 훨씬 유연하고 쉽게 배열 조합 가능

    • 객체 리터럴도 펼침 연산자를 활용하면 2개 이상의 객체 리터럴을 하나로 만들거나, 새로운 객체 리터럴을 만들 수 있다.

      • 상속과는 다르게 복제된 새로운 객체 리터럴을 생성하지만
        여러 개의 객체 리터럴을 조합해서 다양한 객체 리터럴 조합 가능

      • 경우에 따라서 간편하게 상속과 유사한 특성 부여 가능

    var obj1 = {foo: ‘bar’, x:42};
    var obj2 = {foo:’baz’, y:13}:
    var cloneObj = { ...obj1};
    var mergeObj = { ...obj1, ...obj2 };
    
    
    

     

     

    나머지 파라미터의 활용
    • 가변 파라미터를 사용할 수 있도록 해 함수 파라미터를 무한대로 활용 가능

    • ES6에서 추가된 함수 파라미터를 확장하는 기능

    • 나머지 파라미터를 사용하면 함수의 파라미터 개수별로 별도의 함수를 정의할 필요가 없다.

    • 함수 내부에서 가변 파라미터를 처리 가능하도록 추가 파라미터 배열을 제공하기 때문에 가변 파라미터에 대한 대응도 가능

     

    • 가변 파라미터 앞에 3개의 점(...)을 표시해 나머지 파라미터임을 알리고

    • 나머지 파라미터 변수는 배열로 선언되며, 파라미터를 배열에 담다 넘긴다. 파라미터가 없을 경우 빈 배열이 넘어간다.

    function restparams(...args) {// 파라미터를 args 변수(배열)에 담아 함수 내부러ㅗ 넘긴다.
    console.log(args);
    }
    
    restparams(1,2,3,4); // [1,2,3,4]

     

    • 나머지 파라미터는 화살표 함수에도 동일 사용 가능

    • 필수 파라미터는 별도의 변수로 함수로 전달되며, 파라미터 개수가 2개가 초과될 경우, 초과되는 파라미터만 나머지 파라미터 배열에 담겨서 전달된다.

    • 파라미터 개수가 필수 파라미터 개수보다 작은 경우 나머지 파라미터는 빈 배열로 전달 되며, 부족한 필수 파라미터는 “Undefined”가 전달

    • 나머지 파라미터는 반드시 마지막에 오는 파라미터로 사용

    • 나머지 파라미터가 마지막 파라미터가 아니면 오류가 발생

    • 나머지 파라미터는 배열이기 때문에 순환 구문을 사용해 파라미터를 손쉽게 처리 가능하다는 장점이 있다.

    function sum(a,b, ...args) {
    let result = 0;
    if(a != undefined) {result = a;} else {return 0;}
    if(b != undefined) {result += b;}
    args.forEach(function(arg) {
    result += arg;
    });
    return result;
    }
    console.log(sum(1,2,3,4)); //10
    console.log(sum(1,2)); // 3
    console.log(sum(1)); // 1
    
    • 위 구현 방법은 화살표 함수와 reduce() 메서드를 사용하면 아주 간결하게 만들 수 있다.

    • reduce() 메서드는 콜백 함수(리듀서 함수로 정함)로 배열 요소들의 누적 계싼 결과 값을 얻는 메서드
      배열의 누적 계산 값을 구하는 배열 메서드.

    function sum(a,b, ...args) {
    let result = 0;
    if(a != undefined) {result = a;} else {return 0;}
    if(b != undefined) {result += b;}
    result += args.length > 0 ? args.reduce((subsum, arg) => subsum+=arg) : 0;
    }
    console.log(sum(1,2,3,4)); //10
    console.log(sum(1,2)); // 3
    console.log(sum(1)); // 1

     

     

    화살표 함수 기초
    • ES6에서 새롭게 도입된 함수 표기 방법

    • 함수 전체의 구조를 단순화하는 장점

    function add(a,b) { return a+b; }
    let add = (a,b) => a+b;
    • 위와 같이 한 문장으로 된 연산 식 같은 형태로 단순화 가능

    • 표기 규칙

    규칙

    조건

    파라미터

    0개 - 빈괄호() 반드시 표기 -()=>{}
    1개 - () 생략 가능 - arg1 => {}
    2개 이상 - () 파라미터들을 감싸서 표기 -(arg1, arg2) => {}

    return 구문 사용

    블록({})으로 코드를 감싼 경우 반환할 값이 있으면 반드시 return문으로 반환
    블록으로 감싼 코드에 return문이 없을 경우 “undefined”가 반환 됨
    블록을 생략할 경우 “return” 생략 가능

    • 최소 2개 이상의 다양한 파라미터를 받는 함수는 다음과 같이 표현 가능

    let multiply = (a,b, ...args) => {
    let result = a * b;
    args.forEach(item => result *= item);
    return result;
    }
    console.log(multiply(1,2,3,4)); //24
    • 콜백 함수와 익명 함수(함수 이름이 없는 함수)에도 화살표 함수 사용 가능

    setTimeout(()=>console.log(‘timeout’), 3000);
    items.forEach(item => console.log(item.value);});

     

     

     

    고차함수의 이해 High-order function
    • 함수를 인자로 받거나, 다른 함수를 반환하는 함수를 고차함수라고 한다.

    • 함수형 언어에서 코드의 효율성을 높이는 기능

     

    • 일급 함수 First-class

      • 1급 함수, 1급 객체는 인자를 전달 가능하고, 반환 값을 반환 가능한, 변수에 담아 호출할 수 있는 객체 또는 함수

    • 자바스크립트는 함수형 객체지향 언어이며, 함수도 일종의 객체다.

    • 자바스크립트 함수는 이 조건에 부합하여, 자바스크립트 함수는 일급 객체 또는 일급 함수가 된다.

     

    • 고차함수는 인자로 함수를 넘길 수 있거나, 함수를 반환하는 함수를 말한다.

    • 인자로 함수를 넘길 수 있고 함수를 반환할 수도 있는 일급 함수인 자바스크립트 함수는 고차함수가 된다.

     

    • 자바스크립트 내장 객체 중 고차 함수를 가장 많이 사용하는 객체가 배열

      • 예를들어 reduce(), map()

      • map의 예

    const arr =[1,2,3,4,5];
    const arr2x = [];
    for(let i=0; i<arr.length; i++) arr.push(arr[i]*2);
    console.log(arr2x); // [1,2,3,4,5];
    
    arr2x = arr.map(item=>item*2):
    console.log(arr2x); // [1,2,3,4,5];
    • 같은 기능을 위처럼 간겨랗게 구현 가능하며, map에서 “item=>item*2”로 작성한 함수가 고차 함수

     

     

    변수의 스코프(Scope)와 스코프 체인(Scope Chain)의 이해
    • 함수 안의 로컬 변수

      • var은 let과 달리 블록, 구문 단위의 스코프 구분이 없다.

      • 함수 안 어디에서 정의되었든지, 자바스크립트 호이스팅에 의해 변수 정의가 함수 맨위로 끌어올려 지기 때문에 함수 내부 전역 변수로 처리된다. 

    var name = “out”;
    function run() {
    if(true) {
    var name = ‘in’;
    }
    console.log(name);  “in”
    return name;
    }
    run();
    console.log(name); // “out”
    
    
    • 함수 안의 중복 선언 변수

      • 자바스크립트는 변수명을 중복 선언해도 에러가 나지 않는다.

      • 중복 선언된 경우 가장 가까운 위치에 선언된 변수를 사용

      • var name =’name1’;

    function run() {
    var name = ‘name2’;
    var name = ‘name3’;
    console.log(name); // “name3”
    return name;
    }
    run();
    console.log(name); // “name1”

     

    • 함수 스코프 체인

      • 함수가 중첩되거나, 함수에서 다른 함수를 호출하는 경우 함수 스코프 체인에 따라 변수 선언을 찾게 된다.

      • 호출한 함수를 역으로 따라 올라 가면서 변수를 찾고, 최종적으로 전역 변수를 찾게 된다.

    var a = 1;
    var b = 5;
    function outerFunc() {
    function innerFunc() {
    a = b;
    }
    console.log(a); // “1”
    a = 3;
    b = 4;
    innerFunc();
    console.log(a); // “4”
    var b = 2;
    }
    outerFunc();

     

     

    생성자 함수 Generator Function
    • ES6에서 새롭게 도입된 제너레이터 함수는 반복되는 작업을 객체지향적으로 해결하기 위해 나온 함수형 해결책

    • 재귀형 반복작업을 함수 형태로 완성시켜주지만, 일반함수로 재귀형 기능을 구현하는 것보다 기능적으로나, 가독성으로나 더 나은점이 없다.

     

    • 반복자(Iterator, 이터레이터)

      • 반복되는 연산 작업을 함수를 사용해 구현하는 방식.

      • 함수 안에 단위 실행 1번을 실행하는 객체 리터럴과 현재값을 유지하는 변수를 생성해 사용자가 실행단위 별로 개별 실행할 수 있게 만드는 구현 방식

    function calSum(start = 1, end = Infinity) {
    	let current = start;
    	let sum = 0;
    	let accumulate = {
    		next : function() {
    		let ret = null;
    		if(current <= end) { // 마지막 정수 값을 포함해 합계
    			ret = {value: current, done: false}
    		} else {
    			ret = {value: sum, done: true}
    		}
    	sum += current;
    	current++;
    	return ret;
    		}
    	}
    	return accumulate;
    }
    
    let calc = calcSum(1, 10);
    let result = calc.next();
    console.log(“처음실행: “);
    console.log(result); // {value: 1, done:false}
    while(!result.done) {
    	result = calc.next();
    }
    console.log(“합계출력:  “);
    console.log(result); // {value: 55, done:true}
    

     

    • 이터레이터는 로직을 구현하는데 필요한 모든 것을 하나의 함수 안에 내장해서 캡슐화를 하고, 단일 메서드인 next()를 호출해 한 개의 반복 실행 단위를 실행

    • 객체지향적인 구현 방법이지만, 단일 함수 안에서 루프를 돌아 결과 값을 반환 받는 것보다 좋을게 그다지 없다.

    • 현재 위치 값을 알고 있고 한번에 반복되는 실행 로직을  1번씩 실행하는 구현 방법을 반복자, 또는 이터레이터라고 하며, 이렇게 이터레이터로 표현 가능한 함수를 이터러블하다고 한다.

    • 객체 지향 적인 캡슐화된 접근이 유용한 경우는 단위 실행을 하는 중간 상태를 유지해야 하고, 중간 상태에 따라 분기를 해야하는 경우

     

    • 생성자 함수

      • 이터레이터는 내부에 순환 반복을 도는데 필요한 현재 상태 값을 유지해야할 필요가 있다.

      • 객체 지향 관점에서 함수를 캡슐화 하는데 전역 변수에 접근하기 위한 참조를 계속 유지하는 것과 같은 식

     

      • 생성자 함수는 이 현재 상태 값을 유지하지 않을 수 있게 해주는 구현 방법

      • 이터레이터가 캡슐화라는 구현 방식에 대한 접근이라면

      • 생성자 함수는 캡슐화를 위해 추가된 문법을 제공

     

      • “function*” 함수를 선언하면 이 함수는 생성자 함수로 선언한 것이고, 생성자 함수 구현 로직과 추가의 생성자 함수 키워드를 사용 가능

    function* calcSum(start =1, end =Infinity) {
    	let sum = 0;
    	for(let i=start; i<=end; i++) {
    		sum += i;
    		yield i;
    	}
    	return sum;
    }
    
    let calc = calcSum(1, 10);
    let result = calc.next();
    console.log(result);  // {value:1, done: false}
    while(!result.done) result = calc.next();
    console.log(result); // {value: 55, done: true}
    • 시작 정수 값부터 끝 정수 값까지 for문으로 순환하여 합을 구하는 로직이지만, 루프를 1번만 실행하고, 선언되지 않은 next() 함수를 호출하는데 아무렇지도 않게 실행된다.

    • 생성자 함수의 객체 지향적인 접근 방법은 캡슐화 측면에서 간결하고 성공적이지만, 가독성을 떨어뜨린다.

    • yield : 현재 도는 루프의 반복문 변수의 현재 값을 상태 값으로 넘긴다.

      • 반복문 변수는 value 속성으로 반환

    • next : 내장 메섣, 이터레이터에서 객체 리터럴의 메서드 이름을 원하는대로 바꿔도 되지만, 생성자 함수에서는 next()로 고정.

    • 순환문 반복 중 해당 루프 변수값에 해당하는 실행 1회만 실행하고 현재 상태객체를 반환

     

    • 앞서 생성자 함수의 예는 우리가 익히 아는 재귀 순환형 함수로 다음과 같이 구현 가능

    function calcSum(start=1, end=Infinity) {
    	let sum = 0;
    	let current = start;
    	return function calc() {
    		if(current <= end) {
    			sum += current;
    			current++;
    		}
    		return sum;
    	}
    }
    
    let calcFunc = calcSum(1, 10);
    let sum = 0, currSum = 0;
    do {
    	sum = currSum;
    	currSum = calcFunc();
    } while(sum < currSum);
    console.log(sum) // 55
    • 위 함수는 자바스크립트의 실행 상태를 기억하는 클로저를 활용해 누적 합을 구하는 재귀형 함수 호출을 사용한 것

    • 함수의 실행 구조가 명확하게 구분되고, 함수를 한번 호출하면 현재 기억된 상태 값을 기준으로 실행한다는 것을 알 수 있다.