Doby's Lab

[자바스크립트/JavaScript #1] first-class function, hoisting 될까 안 될까? 본문

카테고리 없음

[자바스크립트/JavaScript #1] first-class function, hoisting 될까 안 될까?

도비(Doby) 2021. 7. 25. 14:22

자바스크립트 공부를 하다가 내 눈에는 이상한 점을 발견하여 포스팅을 하게 되었다.

const print = function () {
    console.log('print');
};
print();

다음 코드를 실행하면 아무 문제없을 것이다.

허나,

print();
const print = function () {
    console.log('print');
};

이 코드는 문제를 일으킨다.

[Uncaught ReferenceError: Cannot access 'print' before initialization]

해당 코드가 자바스크립트 엔진에서 돌아가는 원리는 다음과 같다.

//const는 재할당할 수 없지만 엔진의 설명을 위해
const print; //print라는 변수에 아무 것도 선언되지 않았다.
print(); //에러 발생
print = function () {
    console.log('print');
};

즉, 변수 선언 자체는 hoisting이 되지만 변수에 선언된 내용은 hoisting이 되지 않은 것으로 볼 수 있다.

>> 함수(first-class function)를 call 하기 전에 함수는 선언이 되어있어야 한다.

 

다음 코드는 어떨까

function randomQuiz(answer, printYes, printNo){
    if (answer === 'love you'){
        printYes();
    }
    else{
        printNo();
    }
}
const printYes = function () {
    console.log('yes!');
};
const printNo = function print() {
    console.log('no!');
};

randomQuiz('wrong', printYes, printNo);
randomQuiz('love you', printYes, printNo);

randomQuiz라는 함수에서 printYes와 printNo라는 함수를

선언되기 전에 사용하고 있다. 그렇지만 에러가 나지 않는다.

왜 그럴까?

위 코드는 Call Back이라는 개념이 사용되어 그렇다.

(+수정)

----

코드 블록 안의 randomQuiz는 원래 function randomQuiz (answer) {... 와 같이 작성되었었다.

function randomQuiz (answer, printYes, printNo)로 수정하였다.

수정되기 전의 코드도 정상적으로 작동이 되지만

Call-Back을 공부하다 보니 '매개변수에 콜백을 할당한다'라는 개념을 벗어나

혼란이 왔었기 때문이다.

Call-Back function에 관한 내용은 아래에서 다뤘다.

 

----

맨 위에서 봤던 print함수는 print가 선언되기 전에 함수를 call 하여 에러가 발생한다. (2번째 코드 블록)

randomQuiz라는 함수는 어떠한 경우를 만족할 때, printYes나 printNo가 선언된 곳으로 찾아간다.

그래서 마지막에 randomQuiz라는 함수를 call 할 때, 3가지 함수가 다 선언되었으므로 에러가 나지 않는 것이다.

 

에러가 나는 경우는 아래와 같은 경우로 코드가 작성되었을 때 나타난다.

function randomQuiz(answer){
    if (answer === 'love you'){
        printYes();
    }
    else{
        printNo();
    }
}

randomQuiz('wrong', printYes, printNo);
randomQuiz('love you', printYes, printNo);

const printYes = function () {
    console.log('yes!');
};
const printNo = function print() {
    console.log('no!');
};

결론적으로 자바스크립트에서는 함수(first-class function)를 실행시키기 위해

해당하는 함수가 선언되어 있어야 하는 것이다.

 

first-class function은 변수에 함수를 할당하는 것이다.

변수를 선언할 때, 모든 변수가 hoisting 된다. 변수에 할당된 함수도 마찬가지다.

허나, 변수(first-class function)를 call 할 때 변수에 함수가 할당되어 있는지 확인하는 것이 이번 포스팅의 핵심이다.

 

마지막으로, 일반 function과 first-class function의 차이를 다음과 같이 확인할 수 있다.

//일반 function과 first-class function의 차이를 확인하기 위해

printThis();

function printThis(){
    console.log(`this`);
}
//this를 출력함
//이유: function의 선언과 변수의 선언은 hoisting 되기 때문이다.
printThis2();

const printThis2 = function(){
    console.log('this');
}
//this를 출력하지 않음
//변수 자체는 hoisting이 되었지만 함수 내용이 선언되지 않은 채 call을 했기 때문