20210704 JavaSciprt DeepDive 02 : 타입 변환, 단축평가, 옵셔널 체이닝(?.), null 병합 연산자(??), 객체 리터럴, 프로퍼티, 원시값 vs 객체, 복사, 함수(즉시 실행 함수, 재귀함수, 중첩함수, 콜백함수, 고차함수, immutablility 불변성, 선언문과 표현식 등)

12 분 소요

JavaScript Deep Dive 02


용어 및 중요사항 정리


타입 변환


  • 타입 변환 : 기존 원시 값을 사용해 다른 타입의 새로운 원시값을 생성하는 것
    • 명시적 타입변환, 암묵적 타입 변환 둘다, 원시값은 변경 불가능한 값(imutable value)이라서 기존 원시값을 직접 변경하는 것은 아님 (부수 효과X, 재할당X)


  • 암묵적 타입 변환(implicit coercion), 타입 강제 변환(type coercion) : 표현식을 평가하는 도중 자바스크립트 엔진에 의해 암묵적으로 변환되는 것


  • 문자열 타입으로 암묵적 변환
    • 문자열 연결 연산자로 (+)가 작용 하는 경우, 문자열 이외의 것들 문자열 타입으로 변환
      • Type + ‘’ -> ‘Type’
      • Symbol 타입의 경우에만 타입 에러 발생
    • 템플릿 리터럴의 표현식 삽입의 경우, 삽입하는 표현식이 암묵적으로 문자열 타입으로 변환


  • 숫자 타입으로 암묵적 변환
    • 산술 연산자가 작용하는 경우, 피연산자는 모두 숫자이어야 함으로 암묵적으로 숫자타입으로 변환 (숫자로 변환 불가한 경우 NaN 반환)
    • 비교 연산자가 작용하는 경우, 피연산자는 모두 숫자이어야 함으로 암묵적으로 숫자타입으로 변환
    • 단항 연산자가 작용하는 경우, 피연산자를 숫자 타입값으로 암묵적으로 변환
      • NaN을 반환 : 문자열, undefined, {}, [1, 2], function(){}
      • type error를 반환 : symbol


  • 불리언 타입으로 암묵적 변환
    • 제어문(if, for 등..), 삼항 조건 연산자의 경우, 조건식의 평가 결과가 모두 불리언 타입으로 변환
    • Truthy, Falsy : 불리언이 아닌 값을 참, 거짓으로 평가 되는 것
      • Truthy: true, ‘string’, {}, []
      • Falsy: false, undefined, null, 0, -0, NaN, ‘’


  • 명시적 타입 변환, 타입 캐스팅 : 개발자가 의도적으로 값의 타입을 변환하는 것
    • 표준 빌트인 생성자 함수 호출 방법 (new 없이)
    • 빌트인 메서드 사용하는 방법


  • 문자열 타입으로 명시적 변환:

    • String 생성자 함수 호출(new 없이)
    • Object.prototype.toString 메서드 사용
    • 문자열 열결 연산자 사용
    // String 생성자 함수
    String(1);
    // Object.prototype.toString
    (1).toString();
    // 문자열 열결 연산자
    1 + "";
    


  • 숫자 타입으로 명시적 변환:

    • Number 생성자 함수 (new없이)
    • parseInt, parseFloat 함수(문자열만 가능)
    • +단항 산술 연산자
    • *산술연산자(이항)
    // Number 생성자 함수
    Number("0");
    // parseInt
    parseInt("0") + "0";
    // 단항 연산자
    +"0";
    // 산술 연산자
    "0" * 1;
    


  • 불리언 타입으로 명시적 변환:

    • Boolean 생성자 함수 (new 없이)
    • ! 부정 논리 연산자를 두번 사용하는 방법
    // Boolean 생성자 함수
    Boolean("a");
    // !! 사용 (반대로 됬다 다시 반대로 되서 자신으로 돌아옴)
    !!"a";
    


단축 평가


  • 단축평가 : 표현식 평가 도중에 평과 결과 확정시 나머지 평가 과정 생략하는 것

  • 논리연산자를 활용한 단축평가 : 논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환 하는 것

    true || anything; // true (바로, 확정나는 것이면 그 뒤로 평가 안함)
    false || anything; // anything (결정을 확정 하는 곳은 평가를 안하고 그대로 나옴)
    1 || anything; // 1
    true && anything; // anything
    false && anything; // false
    0 && anything; // 0
    
  • 논리연산자를 활용한 단축 평가 활용

    • 단축 평가를 활용하여 if문을 대체 가능
      • Truthy 값은 &&, Falsy값은   으로 if문 대체


  • null, undefined인 자료가 객체인줄 알고 프로퍼티가 있다고 생각하고 참조하는 경우, error 발생 예방
  • 주의) 단축평가의 경우 0 ,’‘은 객체로 평가 될 떄도 있음 (대체하여 옵셔널 체이닝 사용 가능)
var elem = null;
var value = elem && elem.value; // null


  • 함수 매개변수에 기본값 설정

    • 함수 호출시 인수 전달하지 않는 경우 해당 함수 실행시 발생할 에러 방지
    // 논리연산자 단축 평가
    function getStringLength(str) {
      str = str || "";
      return str.length;
    }
    // es6 방식
    function getStringLength(str = "") {
      return str.length;
    }
    




  • 옵셔널 체이닝을 활용한 단축평가
  • 옵셔널 체이닝 연산자(?.) : 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환, 그렇지 않으면 우항의 프로퍼티 참조를 이어감
    • 객체를 가르키기 기대하는 변수가 null, undefined 체크하고 프로퍼티 참조시 유용 (옵셔널 체이닝 or 단축평가)
    • 0, ‘‘의 경우에도 체크가 가능함
var elem = null;
// 옵셔널 체이닝 단축평가
var value = elem?.value;
console.log(value); // undefined
// 논리 연산자 단축평가
var value = elem && elem.value;




  • null 병합 연산자(??) : 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환, 그렇지 않으면 좌항의 피연산자 반환

    • 변수에 기본값 설정시 유용
    • null 병합 연산자의 경우 좌항 피연산자 falsy말고 정확히 null, undefined이어야 함
    // null 병합 단축평가
    var foo = null ?? "default string";
    console.log(foo); // "default string"
    
    // 논리 연산자 단축평가
    var foo = "" || "default string";
    




객체 리터럴


  • 객체 타입 : 다양한 타입의 값을 하나의 단위로 구성한 복합적인 자료구조
    • 객체 타입은 변경 가능한 값임 (mutable value)
    • 원시타입은 변경 불가 값임(immutable value)
    • 0개 이상의 프로퍼티로 구성됨
    • 프로퍼티: 객체의 상태를 나타내는 값으로, key(프로퍼티 키) - value(프로퍼티 값)로 구성됨
    • 프로퍼티 값: 자바스크립의 모든 값이 가능함(일급 객체인 함수도 가능)
    • 메서드(method): 프로퍼티 참조하고 조작할 수 있는 동작으로, 프로퍼티 값이 함수인 경우의 프로퍼티를 말함
    • 자바스크립트에서 객체와 함수는 떨어 질수 없는 개념임


  • 객체지향 프로그래밍의 객체 : 클래스와 인스턴스를 포함한 개념
  • 인스턴스 : 클래스에 의해 생성되어 메모리에 저장된 실체
  • 클래스 : 인스턴스를 생성하기 위한 템플릿


  • 클래스 기반 객체 지향 언어 : new 연산자와 함께 생성자(constructor)를 호출하여 인스턴스 생성방식으로 객체 생성
  • 프로토타입 기반 객체 지향 언어(javascript) : 다양한 객체 생성방법을 지원
    • 객체 리터럴, Object 생성자 함수, 생성자 함수, Object.create 메서드, 클래스(ES6)


  • 객체 리터럴 : 객체 생성 방법중 가장 일반적이고 간단한 방법, { }사용, 변수할당 시점에 객체 리터럴 해석해서 객체 생성
    • 코드블록과 다르게 객체 리터럴은 값으로 평가되는 표현식이므로, 세미콜론을 붙임
    • 객체를 생성하고, 동적으로 추가도 가능


  • 프로퍼티 : 객체는 프로퍼티의 집합, 프로퍼티는 키-값으로 구성

    • , 쉼표로 구분하여 프로퍼티 나열
    • 프로퍼티 키 : 프로퍼티 값에 접근할 수 있는 식별자로, 빈 문자열을 포함하는 모든 문자열 또는 심벌 값을 사용할 수 있음
      • 식별자 네이밍 규칙에 유효한 이름인 경우 따옴표 생략 가능, 유효하지 않으면 따옴표로 묶어야 함
      • 프로퍼티 키를 동적으로 생성하는 경우 key 표현식에 [] 대괄호로 묶어야 함
      • 문자열, 심벌 값 외의 값은 암묵적으로 문자열로 타입 변환됨
      • 중복된 프로퍼티 키인 경우 덮어 씀
    • 프로퍼티 값 : JS의 모든 값


  • 프로퍼티 접근 :
    • 마침표 표기법 : 객체 표현식.프로퍼티 키
    • 대괄호 표기법 : 객체 표현식[‘프로퍼터 키’]
      • 대괄호 표기법시, 프로퍼티 키는 무조건 따옴표로 감싼 문자열
      • 숫자로 이뤄진 문자열 따옴표 생략 가능
    • 식별자 네이밍 규칙 준수 하면 둘다 사용 가능, 준수 하지 않으면 대괄호 표기법만 가능
    • 존재하지 않는 프로퍼티에 접근시 undefined 반환


  • 프로퍼티 값 갱신 : 이미 있던 프로퍼티에 값을 할당하면 갱신됨
  • 프로퍼티 동적 생성 : 없는 프로퍼티에 값 할당시 동적으로 프로퍼티 생성 되고 값도 할당됨
  • 프로퍼티 삭제 : delete 연산자로 특정 프로퍼티 삭제 가능 (delete 프로퍼티 접근 표현식)
    • 없는 값을 삭제하면, 에러 없이 무시됨


  • 객체 리터럴 확장 기능:

    • 프로퍼티 축약 표현: 프로퍼티 값으로 변수 사용하는 경우 변수와 프로퍼티 키가 동일한 이름일 경우 프로퍼티 키 생략 가능
    let x = 1,
      y = 2;
    const obj = { x, y }; // {x: 1, y: 2}
    
    • 계산된 프로퍼티 이름(computed property name):
      • ES5는 외부에서만, ES6에서는 객체 리터럴 내부에서도 계산된 프로퍼티 이름으로 프로퍼티 키 동적 생성 가능
    • 메서드 축약 표현:

      • 프로퍼티 값으로 함수를 넣어 메서드를 만드는 경우, function 키워드 생략한 축약 표현 사용 가능
      const obj = {
        name: "kim",
        hi() {
          console.log("hi!" + this.name);
        },
      };
      


원시 값과 객체 비교


차이점 원시 객체
값 변경 변경 불가 값 변경 가능 값
값 저장 실제 값 저장 참조값 저장
값 복사 전달 값에 의한 전달 참조에 의한 전달


  • 변경 불가능한 값 : 한번 생성된 원시 값은 읽기전용 값으로 변경 불가하다(변수 값 변경(상수, 변수) 이야기가 아님, 값 자체를 이야기 함)
    • 재할당시, 새로운 메모리 확보 -> 값을 할당 -> 변수의 메모리 참조 주소 변경


  • 문자열 : 원시 타입이며 문자의 집합으로 문자(character) 1개당 2바이트의 공간이 필요함
    • 유사 배열 객체로 이터러블이라서 배열과 유사하게 각문자에 접근 가능함
    • 하지만, 문자에 접근해서 해당 문자만 다른 값으로 할당하여 변경 불가하다. (변수에 새로운 문자열 재할당은 가능)


  • 값에 의한 전달 : 원시 값을 갖는 변수(A)를 다른 변수(B)에 할당하면, 할당 받는 변수(B)에 원시 값이 복사되어 전달됨 (새로운 메모리에 값만 복사됨, 새로운 메모리 주소를 사용하게 됨)
    • A, B는 다른 메모리 공간에 저장된 별개의 값임 ->A, B의 변화는 서로에게 영향을 주지 않음
    • 파이썬의 경우에는 새로운 메모리 주소가 아닌 같은 메모리 주소를 사용하며 한쪽에 다른 값을 재할당 했을 때, 새로운 메모리 공간에 재할당 되어 비로서 새로운 메모리 주소를 사용하게 됨


  • 객체 : 객체의 경우 내부 구성요소를 동적으로 변화 시킬 수 있기 때문에, 메모리 공간 크기를 사전에 정해 둘 수 없음 -> 프로퍼티 접근이 비효율 적임 -> V8 엔진은 히든 클래스 방식으로 개선함
  • 해시테이블, 연관배열, map, dictionary, lookup table : key-value 구조의 자료 구조


  • 변경 가능한 값 : 객체 타입의 값이며, 재할당 없이 객체를 직접 변경할 수 있음
    • 참조 값 : 생성된 객체가 저장된 메모리 공간의 주소
    • 식별자(객체 저장 공간 주소가 저장된 메모리 주소) -> 참조값(실제 객체가 저장된 메모리 공간 주소) -> 객체가 저장된 메모리
    • 객체를 할당한 변수를 참조하면 메모리에 저장된 참조 값을 통해 실제 객체에 접근
    • 여러개의 식별자가 하나의 객체를 공유 가능함


  • 얕은 복사 : 객체의 한단계 까지만 복사하는 것 (서로 다른 메모리를 사용하게 하기 위해)
  • 깊은 복사 : 객체에 중첩되어 있는 객체까지 모두 복사하는 것 (서로 다른 메모리를 사용하기 위해서), 원시타입의 값이 복사 되는 것을 이야기 하기도 함(원시타입의 경우 얕은 복사가 발생하지 않음으로)
    • lodash의 cloneDeep을 이용하여 가능함


  • 참조에 의한 전달 : 객체를 가르키는 변수를 다른 변수에 할당하는 경우 참조 값이 복사되어 전달
    • 메모리 주소는 다르지만, 같은 참조 값을 가짐 (두개의 실별자가 하나의 객체를 공유)
    • 참조값은 그대로 이고, 객체가 실제 저장된 곳의 데이터가 변경됨으로 공유하게 됨(서로 영향을 주고 받음)


  • 참조에 의한 전달, 값에 의한 전달 모두 식별자가 기억하는 메모리 공간에 저장되어 있는 값을 복사해서 전달한다는 것은 동일 -> 값에 의한 전달임
  • 다른 언어에는 pointer가 존재하기 때문에 참조에 의한 전달이 딱 맞게 떨어지지만,자바스크립트의 경우에는 pointer가 없어 살짝 다른 개념임
  • 값의 비교하는 비교 연산자의 경우 정확하게 메모리가 아닌 값을 보고 비교함


var person1 = {
  name: "kim",
};
var person2 = {
  name: "kim",
};
console.log(person1 === person2); // false 참조값(메모리 주소)이 다르므로
console.log(person1.name === person2.name); // true kim, kim 으로 값이 같으므로




함수


  • 함수(function) : 일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것
    • 함수 정의를 통해 함수를 생성함 -> 함수 리터럴도 평가되어 객체 값을 생성함 (함수 = 호출 가능한 객체)
    • 함수의 사용 -> 코드의 재사용성 향상, 유지보수 평의성 향상, 코드의 신뢰성 향상
    • 매개변수(parameter) : 함수 내부로 입력을 전달 받는 변수
    • 인수(argument) : 함수 내부로 받는 입력
    • 반환값(return value) : 함수를 거쳐 외부로의 출력하는 값, 함수 실행뒤 반환되는 값
    • 함수호출(function call/invoke) : 인수를 매개변수로 함수에 전달하여 함수를 명시적으로 실행지시하는 것 (함수 이름으로 호출하는 것이 아닌 함수 객체를 가르키는 식별자로 호출)


  • 함수 리터럴 : 함수를 생성하기 위한 기호 방식
    • function키워드
    • 함수이름 : 식별자(네이밍 규칙 준수), 함수 몸체 내에서만 참조 가능한 식별자, 생략 가능함(기명, 무기명 함수)
    • 매개 변수 목록 : 소괄호로 감싸고 쉼표로 구분, 매개 변수 목록은 순서의미가 있음, 몸체내에서 변수와 동일 취급(네이밍 규칙 준수)
    • 함수 몸체: 함수 호출시 일괄 실행되는 문들이 있는 코드블록, 함수 호출시 실행


  • 함수 정의 : 함수 호출하기 전 매개변수, 실행문, 반환할 값 등을 지정하는 것

  • 함수 선언문

    • 표현식이 아닌 문
    • 함수 이름 생략 불가
    • 함수 호이스팅 O (런타임 전에 식별자 암묵적 생성 -> 함수 객체 할당)
    • 함수 선언문과 함수표현식의 형태는 똑같음 하지만 변수에 할당하냐 안하냐에 차이 (자바스크립트 엔진이 상황에 따라서 문인지 표현식인지 알아서 해석)
    • 선언문의 경우 암묵적으로 외부에서 함수 식별자를 몸체 내에서만 사용할 수 있는 함수 이름으로 함
    function add(x, y) {
      return x + y;
    }
    add(1, 2); // 3 (암묵적)식별자 add , 함수 이름 add
    


  • 함수 표현식

    • 표현식인 문
    • 일급 객체 : 함수를 값처럼 자유럽게 사용가능
    • 변수에 할당되는 값이 함수 리터럴인 문
    • 함수 이름생략 가능
    • 함수 호이스팅 X, 변수 호이스팅O (함수 리터럴은 런타임에 할당문 실행 시점에 평가됨)
    • 리터럴의 경우 함수 이름은 몸체 내에서만 참조 가능한 식별자
      • 외부에서는 함수를 가르키는 식별자가 없음
    const add = function foo(x, y) {
      return x + y;
    };
    
    add(1, 2); // 3 식별자로 호출
    foo(1, 2); // Reference Error 함수 이름으로 호출 시도 했기 때문
    
    (function bar() {
      console.log("bar");
    });
    bar(); // Reference Error 리터럴이므로 외부에서는 함수를 가르키는 식별자가 없음
    // 식별자 없음 , 함수 이름 bar
    


  • 변수 호이스팅 vs 함수 호이스팅
    • 런타임전 둘다 식별자 생성하고 초기화가 다름
    • 변수는 undefined로, 함수는 함수 객체로 초기화


  • 생성자 함수 : 객체를 생성하는 함수


  • Fucntion 생성자 함수

    • 일반적이지 않은 함수 생성 방법
    • 다른 함수 생성방식에 의한 함수와 다르게 동작함 (클로저를 생성하지 않음)
    const add = new Function("x", "y", "return x+y");
    


  • 화살표 함수

    • function 키워드 대신 화살표(=>)를 사용해 간략한 방법으로 함수 선언(항상 익명 함수)
    • 생성자 함수로 사용 불가
    • this 바인딩 방식이 다르고
    • prototype 프로퍼티가 없음
    • arguments 객체를 생성하지 않음
    const add = (x, y) => x + y;
    


  • 함수 호출: 함수 식별좌와 한쌍의 소괄호인 함수 호출 연산자로 호출
    • 함수 호출시 실행 흐름을 중단하고 호출된 함수로 실행 흐름을 옮김


  • 인수 : 함수를 호출 할때 지정, 표현식이어야 함, 개수와 타입 제한 없음
  • 매개변수 : 함수 정의할 때 선언, 몸체 내부에서 변수와 동일 취급 (마찬가지로 undefined로 초기화 된 이후 인수가 순서대로 할당), 스코프는 함수 내부
    • 매개변수는 적을 수록 좋고 함수는 하는일이 가급적 작게 만들어야 함
    • 매개변수 3개 사용 권장, 많이 들어가게 되면 1개의 인수를 객체로 넣게 하자
  • 인수의 개수와 매개변수 개수가 일치하지 않아도 에러가 발생하지 않음
  • 매개변수 개수 > 인수개수 인경우, 할당 되지 않은 매개변수는 undefined
  • 매개변수 개수 < 인수개수 인경우, 넘치는 인수는 암묵적으로 arguments 객체 프로퍼티로 보관됨


  • arguments 객체 : 매개변수 개수를 확정 할 수없는 가변 인수 함수를 구현시 사용
  • 인수 확인 : 인수의 타입, 인수의 전달 개수 확인 필요 -> 잘못된 사용 방지
    • typeof를 활용한 조건식으로 에러처리 또는 typescript로 컴파일 에러
    • arguments 객체로 인수 전달 개수 확인 가능
    • 인수가 전달되지 않은 경우 기본값 할당 (단축 평가 방식, 매개변수 기본값 방식)


  • 반환문: return 키워드 및 표현식으로 이루어진 반환문을 사용해 실행 결과를 외부로 반환 가능
    • 함수 호출은 표현식으로 함수 내부 반환문의 실행 결과로 평가되어 나타남
    • 역할1) 함수 실행 중단하고 몸체를 빠져 나옴 (이후의 코드는 실행 X)
    • 역할2) return 키워드 뒤에 오는 표현식을 평가해 반환 (표현식이 없는 경우, undefined가 반환됨)
    • 반환문 생략시 암묵적으로 undefined를 반환
    • 전역에서 반환문 사용시 SyntaxError발생 (nodeJS환경에서는 에러 발생X)


  • 매개변수에 값을 전달하는 방식:
    • 값에 의한 호출(값에 의한 전달) : 인수가 primitive인 경우, 값 자체가 복사 되어 원본 훼손X (부수 효과X)
    • 참조에 의한 호출(참조에 의한 전달) : 인수가 obj인 경우, 참조값이 복사 되어 원본 훼손O (부수 효과O)
      • 외부의 값을 변경하기 때문에 외부 상태가 변하는지 상태 확인이 어려움
      • -> 옵저버 패턴 또는 불변 객체 활용하여 해결


  • 옵저버 패턴 : 객체가 변경되었을 때 객체를 참조를 공유하는 모든 이들에게 변경사실 통지
  • 불변 객체 : 객체를 변경 불가능하게 만들어 상태 변경을 봉쇄
    • 상태변경 필요시, 객체의 방어적 복사 (깊은 복사)를 통해서 새로운 객체를 생성하고 재할당 해서 교체
  • 순수 함수 : 외부 상태에 의존하지 않고, 변경하지 않는 함수 (부수효과X)
    • 동일 인수 전달시 언제나 동일 값 반환
    • 반환한 결과를 재할당을 해줘야 상태가 변경되어 상태 변경 추적이 좋음
  • 비순수 함수 : 외부 상태에 의존하고, 변경하는 함수 (부수 효과O)
    • 외부 상태에 따라 반환값이 달라지는 함수
    • 외부 상태를 직접 참조하거나, 객체를 전달 받은 경우 비순수 함수임
    • 실행하면 상태가 변경 되기 때문에, 언제 실행 했는지 잘 모르면 변경 추적이 힘듦
  • 함수형 프로그래밍 : 순수 함수와 보조함수의 조합을 통해 부수 효과 최대한 억제하여 안정성, 불변성(immutability)을 높이는 프로그래밍


  • 즉시 실행 함수(IIFE): 함수 정의와 동시에 즉시 호출되는 함수(단 한번 호출되고 재호출 불가)

    • 익명함수 활용하여 뒤에 () 호출 연산자 붙여줌
    • 무조건 그룹 연산자로 감싸야 함(감싸지 않으면 syntax Error)
      • 그룹 안에서는 기명함수를 쓰면 error
      • 그룹 안쓰고 밖에서 익명함수 쓰면 함수 선언문으로 인식해서 error
      • 그룹 안쓰고 밖에서 ()호출 연산자 붙이면 구룹 연산자로 인식해서 error
    • 그룹 연산자로 함수 리터럴을 묶으면 함수리터럴을 먼저 평가하여 함수 객체를 생성하기 때문에 이외의 연산자를 사용할 수 있음
    • 일반 함수 처럼, 값 반환, 인수 전달도 됨
    var res = (function () {
      var a = 3;
      var b = 5;
      return a * b;
    })();
    console.log(res); // 15
    
    res = (function (a, b) {
      return a * b;
    })(3, 5);
    console.log(res); // 15
    


  • 재귀함수 : 함수 자기 자신을 호출(재귀 호출)하는 함수
    • 반복 처리를 위해 사용함
    • 함수 표현식의 경우 함수 이름, 함수 식별자로도 재귀 호출 가능
    • 외부에서 함수 호출은 무조건 함수 식별자로 해야함
    • 탈출 조건 (탈출 조건 없으면 스택 오버플로 에러 발생)


  • 외부함수(outer function) : 중첩함수를 포함하는 함수
  • 중첩함수/내부 함수(nested function/inner function) : 함수 내부에 정의된 함수
    • 중첩 함수는 외부 함수 내부에서만 호출 가능
    • 자신을 포함하는 외부 함수를 돕는 헬퍼 함수(helper function) 역할
  • ES6 함수 정의 위치 : 문이 위치할 수 있는 문맥 어디든지 (최상위, 다른 함수 내부, if, for 등의 코드블럭 안에서)
    • 단, if, for문에서 사용하는 것은 바람직 하지 않음


  • 콜백 함수(Callback function) : 변경되는 함수의 로직을 구현하기 위해서, 함수의 매개변수를 통해 다른 함수의 내부로 전달 되는 함수
    • 고차함수를 돕는 헬퍼함수 역할
    • 고차함수에 의해 호출됨
    • 비동기 처리, 배열 고차함수에 활용되는 중요한 패턴임
  • 고차함수(Higher-Order Function) : 매개변수를 통해 함수의 외부에서 콜백함수를 전달받은 함수
    • 콜백함수를 자신의 일부분으로 합성함
    • 필요에 따라 콜백함수에 인수를 전달 할 수 있음
    • 주의) 전달시 함수 자체를 전달해야함, 호출을 전달하는 것이 아니라
    • 콜백함수의 형태는 보통 익명함수로 전달(해당 함수가 많이 반복 된다면, 미리 callback을 외부에서 만들어 전달)
    • 콜백함수는 고차함수가 호출 될때마다 생성됨