-
자바스크립트 함수, 일급 객체, 함수 생성 시점과 함수 호이스팅Frontend/Javascript 2023. 4. 3. 15:13
자바스크립트의 함수는 "일급 객체"이다.
함수가 일급객체라는 것은 함수를 값처럼 자유롭게 사용할 수 있다는 의미이다.
함수가 객체라는 사실은 다른 프로그래밍 언어와 구별되는 자바스크립트의 중요한 특징이다.
함수는 일급 객체이므로 함수 리터럴로 생성한 함수 객체를 변수에 할당할 수 있다.
이러한 함수 정의 방식을 함수 표현식이라고 한다.
// 무명 함수 표현식 var add = function(x, y) { return x + y; }; console.log(add(2, 5)); //7 // 기명 함수 표현식 var add = function foo (x, y) { return x + y; }; console.log(add(2, 5)); // 7 console.log(foo(2, 5)); // ReferenceError: foo is not defined
자바스크립트 엔진은 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 거기에 함수 객체를 할당한다.
즉, 함수는 함수 이름으로 호출하는 것이 아니라 함수 객체를 가리키는 식별자로 호출한다.
함수 이름 add가 아니라 자바스크립트 엔진이 암묵적으로 생성한 식별자 add로 호출한다.
함수 이름과 변수 이름이 일치하므로 함수 이름으로 호출되는 듯 하지만, 사실은 식별자로 호출된 것이다.
함수 리터럴의 함수 이름은 생략할 수 있는데 이러한 함수를 익명함수라고 한다.
함수 이름은 함수 몸체 내부에서만 유효한 식별자이므로 함수 이름으로 함수를 호출할 수 없다.
그래서 위와 같이 함수 이름이 아니라 함수 객체를 가리키는 식별자를 사용해야 한다.
단, 기명 함수 리터럴을 단독으로 사용하면 "함수 선언문"으로 해석된다.
이 경우에는 함수 이름을 생략할 수 없다.
이 때 이 두 가지 표현식의 큰 차이점이 있다. 호이스팅에서 큰 차이를 보인다.
// 함수 참조 console.dir(add); // f add (x, y) console.dir(sub); // undefined // 함수 호출 console.log(add(2, 5)); // 7 console.log(sub(2, 5)); // TypeError: sub is not a function // 함수 선언문 function add (x, y) { return x + y; } // 함수 표현식 var sub = function (x, y) { return x - y; };
이러한 이유는, 함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성 시점이 다르기 때문이다.
이러한 차이를 이해하기 위해, 함수 호이스팅과 변수 호이스팅의 차이를 이해할 필요가 있다.
var 키워드를 사용한 변수 선언문과 함수 선언문은 런타임 이전에 자바스크립트 엔진에 의해 먼저 실행되어 식별자를 생성한다는 점에서 동일하다. 하지만 var 키워드로 선언된 변수는 undefined로 초기화되고, 함수 선언문을 통해 암묵적으로 생성된 식별자는 호이스팅에 의해 undefined로 평가되지만 함수 선언문으로 정의한 함수를 함수 선언문 이전에 호출하면 함수 호이스팅에 의해 호출이 가능하다. 그 이유는.
함수 선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성되고 자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 생성된 함수 객체를 할당하기 때문이다.
여기에서 함수 표현식은 변수에 할다오디는 값이 함수 리터럴인 문이다.
변수 할당문의 값은 할당문이 실행되는 시점, 즉 런타임에 평가되므로 함수 표현식의 함수 리터럴도 실행되는 시점에 평가되어 함수 객체가 된다.
따라서 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다.
함수 표현식 이전에 함수를 참조하면 undefined로 평가된다. 이 때 함수를 호출하면 undefined를 호출하는 것과 마찬가지이므로 타입 에러가 발생한다. 따라서 함수 표현식으로 정의한 함수는 반드시 함수 표현식 이후에 참조 또는 호출해야 한다.
출처: 모던 자바스크립트 딥 다이브 - 위키북스
'Frontend > Javascript' 카테고리의 다른 글
javascript 클로저 예제 및 쓰는 이유 (0) 2023.04.06 javascript 함수 호출 방식에 따른 this 동적 바인딩 (0) 2023.04.04 렉시컬 환경, 실행 컨텍스트, 스코프 (0) 2023.04.03 비동기 함수를 동기로 다루기 callback, promise, async-await (0) 2023.03.14 CORS 이해하기 및 해결방법 (0) 2022.12.21