책 인사이드 자바스크립트를 읽고 정리한 내용입니다.

  • 함수는 일급 객체 ( 변수에 값으로 할당될 수 있고, 함수의 리턴값, 함수의 매개변수로 전달, 객체이기 때문에 동적으로 프로퍼티를 생성할 수 있음)
  • 기본 property : length, prototype
  • prototype과 [[Prototype]] , proto 와의 차이
  • 내부함수와 스코프 체인, 클로져

자바스크립트 함수는 일급 객체이다.

자바스크립트에서는 함수도 객체이다. 자바스크립트의 데이터타입의 참조타입에서도 설명했 듯이 객체는 동적으로 프로퍼티를 추가할 수 있다. 함수도 마찬가지로 객체이기 때문에 동적으로 프로퍼티를 추가할 수 도 있다.

function add(x,y) { return x+y; }
add.status = "OK";
add.result = 5;

이러한 특징 때문에 함수는 다음과 같이 동작할 수 있다.

  • 함수 리터럴에 의해서 생성된다.
  • 변수에 값으로 할당되거나 배열의 값으로 사용된다.
  • 함수의 리턴값으로 사용된다.
  • 함수의 인자로도 전달된다.
  • 함수의 프로퍼티를 동적으로 생성할 수 있다.

이러한 특징이 있는 함수를 일급 객체 라고 부른다.

함수의 기본 property : length와 prototype

함수는 다른 객체들과는 다르게 함수 객체만의 표준 프로퍼티가 있다. ECMA 스크립트에는 모든 함수가 length와 prototype 프로퍼티를 가져야한다고 나와있다.

  • length -- 함수가 정상적으로 사용될 때 기대되는 인자의 개수이다.
  • prototype -- 함수가 생성자로 사용될 때 함수로 인해 만들어진 객체의 부모역할을 하는 프로토타입을 가리킨다.

prototype은 매우 중요하니 자세히 살펴보자.
먼저 헷갈릴 수 있는 요소들을 정리해보았다. 위의 add 함수를 console.dir(add)로 출력해보았다.

스크린샷 2019-05-05 오후 5.41.24.png

  • prototype과 [[Prototype]] or __proto__ 는 같은건가 ?
    NOPE! 자바스크립트 데이터 타입에서 살펴보았듯이 모든 객체에는 자신의 부모 역할을 프로토타입 객체인[[Prototype]] (크롬 브라우저에서는 __proto__ )을 내부 프로퍼티로 가지고 있다.
    add 함수의 부모역할을 하는 프로토타입 객체는 Function.prototype이라는 객체이다.
    반면 함수가 가지고 있는 ex) add.prototype 는 add 함수가 객체의 생성자로 사용이 될때, 새로 만들어진 객체의 부모 프로토타입을 가리킨다.

이 prototype 프로퍼티는 constructor 프로퍼티 하나만 있는 객체를 가리킨다. 이 객체의 constructor는 객체를 가리키고 있는 함수(즉 add 함수)를 참조한다.

function.prototype (1).png

내부 함수와 스코프 체인

함수 안에 또 다른 함수가 있는 경우 이 함수를 내부함수 (inner function)이라고 한다.

function parent(){
 var a = 100;
 var b = 200;

  function child(){
    var b = 300;
    console.log(a);
    console.log(b); 
    }
 child();
}
parent(); // 100 300 
child(); // Uncaught Reference error : child is not defined

🌟 중요 포인트

  • child 함수는 내부 함수이며 함수를 둘러싸고 있는 parent 함수의 변수에 접근이 가능하다. [스코프 체이닝]
  • 변수 b는 child 함수 내에 선언되어 있기 때문에 parent 함수의 변수 b가 아닌 child 변수의 a를 사용한다.
  • 함수 내부에서는 외부 함수의 변수에 접근할 수 있지만 외부에서 내부 함수의 변수로는 접근 하지 못 한다. child 함수는 parent 안에 정의되어 있기 때문에 parent 밖에서 호출했을 때 오류가 발생한다.

하지만 함수 외부에서도 특정함수 내부에 있는 함수를 호출할 수 있는 방법이 있다. 부모 함수가 내부 함수를 리턴 하면 부모 밖에서도 내부 함수를 호출할 수 있다.

function parent(){
 var a = 100;
 var b = 200;

  function child(){
    console.log(b); 
    }
 return child;
}
var inner = parent();
inner();
  • parent()가 child 함수의 참조값을 리턴하기 때문에 inner에도 child의 참조값이 들어간다. 이 때문에 inner 변수에 호출 연산자 ()가 붙으면 parent 함수 밖에서도 child 함수 호출이 가능하다.
    parent 처럼 실행이 끝난 함수의 변수를 참조하는 inner()와 같은 함수를 클로저 라고 한다.