함수를 정의하는 3가지 방법

zumgu_profie

1) 선언 함수 (Declared Function - DF)

// 1. Declared Function
function foo () {
  console.log('hello world - foo');
}

2) 함수 표현식 (Function Expression FE)

함수표현식을 function을 값처럼 사용하는 것을 말합니다. 즉시 실행가능한 코드로 해석 되어지거나 변수나 데이터 구조에 할당되어지고 있음을 의미합니다. 즉, 해당 코드블럭이 실행코드로서 해석되어지며 동시에 코드실행에 따른 결과값을 가지거나 특정 변수에 할당된 값으로 존재합니다.

var bar = function () {
  console.log('hello world - bar');
}

3) Function Constructor (함수 생성자)

객체를 생성하기 위한 함수를 Constructor Function이라고 부릅니다. 함수 객체를 생성하기 위한 함수는 Function이라고 정의되어 있는 Constructor Function 입니다.

var baz = new Function ("console.log('hello world')");

Function Constructor는 새로운 Function 객체를 만듭니다. 자바스크립트에서 모든 함수는 실제로 Function Object 입니다. 자바스크립트 인터프리터는 사실 DF, FE를 모두 Function Constructor를 이용해서 함수 객체로 만들어 줍니다.

자바스크립트 동작 원리 (호이스팅)

호이스팅 이란?

인터프리터가 자바스크립트 코드를 해석함에 있어서 Global 영역의 선언된 코드 블럭을 최상의 Scope 로 끌어올리는 것을 호이스팅 이라고 합니다.

자바스크립트는 인터프리트 시점에서 선언 함수(DF)를 코드의 가장 상단으로 이동(호이스팅) 시켜주기 때문에 아래의 코드는 오류가 일어나지 않게 됩니다.

foo();

function foo () {
  console.log('hello world - foo');
}

output : hello world - foo

실제로 인터프리트 과정을 거친 코드는 아래와 같습니다.

var foo = function foo () {
  console.log('hello world - foo');
}

foo();

그러나 함수 표현식(FE)에서의 호이스팅이 일어나면 bar라는 변수를 undefined로 global scope에 정의하기 때문에 아래의 코드는 에러가 나게 됩니다.

bar(); // output1
console.log(bar); // output2
var bar = function () {
    console.log('hello world - bar')
}

output : TypeError : bar is not a function output : undefined

실제로 인터프리트 과정을 거친 코드는 아래와 같습니다.

// VO (Variable Object)
var bar = undefined;
bar();
console.log(bar);

bar = function () {
   console.log('hello world - bar')
}

그러면 익명함수가 아닌 FE 함수에서의 간단한 예제를 이어서 소개하겠습니다.

function foo () {
  console.log('foo');
}

var bar = function baz () {
  console.log('bar');
}

bar(); // output1
baz(); // output2
foo(); // output3

output1 : bar output2 : TypeError baz is not a function output3 : foo

위와 같은 결과는 왜 일어나게 되는 걸까요? 아래의 인터프리트 과정을 거친 후의 코드를 보면 이해가 되실겁니다.

var bar = undefined;
var foo = function foo () {
  console.log('foo');
}

bar = function baz () {
  console.log('bar');
}

bar();
baz();
foo();

위의코드에서 처럼 인터프리트 과정 후에는 DF 가 위와같이 선언되었습니다. 사실 저희가 함수를 호출하는 것은 변수명으로 함수를 호출한다는 의미입니다. 따라서, FE에서 함수명으로 함수를 호출하는 것이 불가능한 것입니다.

마지막으로 호이스팅 과정에대한 이해를 돕기위한 코드를 소개하겠습니다.

인터프리트 과정을 거치기 이전의 코드는 아래와 같습니다.

var name = '홍구';
var nickname = '줌구';

bar(); // output1
console.log(bar); //output2
foo(); //output3
var bar = function () {
  console.log('hello world - bar');
}

function foo () {
  console.log('hello world - foo');
}

output1 : TypeError : bar is not a function output2 : undefined output3 : hello world - foo

인터프리트 과정을 거친 이후에는 global scope에 선언한 변수가 undefined로 정의되게 됩니다.

// VO (Variable Object)
var name = undefined;
var nickname = undefined;
var bar = undefined;  // FE function이 undefined로 global scope에 정의 된다.

var foo = function foo () {
  console.log('hello world - foo');
} // DF function이 호이스팅 된다.


name = '홍구';
nickname = '줌구';

bar(); // output1
console.log(bar); //output2
foo(); //output3

bar = function () {
  console.log('hello world - bar');
}

Function Level Scope

앗 축구바야됨… 보구 낼 할래…