언어/자바스크립트

[Javascript] 호이스팅(2), 함수선언문, 함수 표현식(익명, 기명)

youngble 2022. 6. 13. 21:04

호이스팅에 관하여 알아야하는 정보중에 알면 좋은 정보는
함수선언문과 함수표현식 이다.

함수선언문

function a(){
 ... 실행 코드
}

a();

함수선언문은 function 정의부만 존재하고 별도의 할당 명령이 없는 것을 의미한다.
호이스팅시 함수선언문은 함수명, a 가 곧 변수명으로 생각하고 실행된다고 생각하면된다.

함수표현식

정의한 function을 별도의 변수에 할당하는 것을 말한다.
함수선언문은 함수명이 반드시 정의되야 하는 반면, 함수표현식은 정의를 해도 되고 안해도된다. 이때 함수표현식은 기명 함수표현식, 익명 함수표현식으로 두가지로 나뉜다.
만약 함수명을 정의했다면 기명, 하지않았다면 익명 함수표현식이라고 정의하였다.

익명 함수표현식

var b = function(){ // 익명 함수표현식. 변수명 b가 곧 함수명
...실행코드
}
b();

익명 함수표현식은 예전같은경우 undefinedunname으로 값이 나와서 기명 함수 표현식을 사용함으로써 디버깅시에 어떤 함수인지 추적할수있게 하여 기명함수표현식이 보다 유리한 측면이있었지만, 이제는 모든 브라우저들이 익명 함수표현식의 변수명을 함수의 name 프로퍼티에 할당하고 있다.

기명 함수표현식

var c = function d(){ // 기명 함수표현식. 변수명은 c, 함수명은 d
	...실행 코드
}
c(); // 실행 OK
d(); // 에러

기명함수의 특징은 외부에서 변수명으로 호츨하면 실행이 되지만 함수명으로 호출하면 에러가 발생한다. 만약 함수 내부에서 호출할때는 변수명으로 호출하든 함수명으로 호출하든 잘 실행되지만 굳이 함수명으로 호출하지않고 변수명으로 호출하는것을 지향한다.

함수 선언문과 함수표형식의 호이스팅

 

console.log(sum(1,2));
console.log(multiply(3,4));

function sum(a,b){
   return a+b;
}

var multiply = function (a,b){
   return a*b;
}

우리가 배운대로 environmentRecord의 정보 수집과정에서 호이스팅을 살펴보면 다음과 같다.

var sum = function sum(a,b){
    return a+b;
}

var multiply;
console.log(sum(1,2));
console.log(multiply(3,4));

multiply = function(a,b){
   return a*b;
}

함수 선언문의 경우는 전체를 호이스팅하며 함수명 sum을 변수명 sum으로 선언과 할당이 위로 끌어올리면서 진행한다.
반면 익명 함수표현식 경우는 변수만 선언하고 할당부분은 원래 자리 그대로 둔다. 따라서 console.log(multiply(3,4)) 실행시 3 과 'multiply is not a function' 에러 메세지를 출력하고 뒷부분은 실행되지 않은체 런타임 종료된다.

 

함수선언문 사용시 문제점

여기서 함수선언문의 호이스팅으로 인해서 초보, 또는 익숙하지 않은 개발자가 혼란스러운것도 있지만 실질적은 협업부분에서 크나큰 문제가 있다. 예를들어 개발자 A, B가 있다고 생각하자 기존에 A라는 개발자가 있었고, 나중에 새로 입사한 B라고 생각했을때 처음에 개발자 A가 sum이라는 함수선언문을 사용하였고 나중에 B 개발자가 같은 이름의 sum이라는 함수선언문을 사용하게 될때의 문제이다. 다음 코드를 보면서 설명해보면

//....여기까지 59번째줄 코드라고 가정

console.log(sum(1,4));

//... 여기까지 99번째줄 코드라 가정
function sum(x,y){  // 개발자 A가 만든 함수선언문 sum
   return x+y;
}

//... 여기까지 199번째줄 코드라 가정
var a = sum(1,2);

//... 여기까지 4999번째줄 코드라 가정

function sum(x,y){ // 개발자 B가 만든 함수선언문 sum
	return x + '+' + y + '=' + (x+y);
}

var c = sum(1,2);
console.log(c);

200번째줄까지 A개발자가 sum이라는 함수선언문을 이용하여 잘쓰고 있다고 생각한다. 해당 두 number 인수를 넘겨주면 더한값을 return 해주는 함수였고 그 값을 a라는 변수에 담아주는 등 잘쓰고 있었는데 개발자 B가 이를 모르고 5000번째 줄에 return 값이 문자열로 출력해주는 sum 함수선언문을 다시 만들었다고 생각해보면, 함수선언문은 호이스팅시 전체를 위로 끌어올리기때문에 A가 작성한 코드가 결국 B가 작성한 sum 함수선언문으로 사용되여 출력되는 문제가 발생하게된다. 동일한 변수명에 서로다른 값을 할당할경우 나중에 할당한 값이 먼저 할당한 값을 덮어씌우기때문이다(override). 이렇게 함수선언문의 호이스팅의 위치를 잘못 이해하고 영향이 없을것이라고 생각하여 커밋, 머지, 배포할 경우 문제가 발생하게 된다는 예이다.

결론: 함수표현식을 써야하는이유

만약 sum함수를 함수표현식으로 정의했다면 A와 B가 의도한대로 실행되고 호출될것이다. 호이스팅을 변수 선언만 올려주고 할당부분은 원래 위치에 있기때문에 순서대로 실행됨으로 문제가 없다.