JavaScript

[JavaScript] 함수 호출시 주의사항(선언함수 vs 익명함수), Hoisting

SangRok Jung 2022. 4. 12. 21:55
반응형

 

함수 호출 시 주의 사항

 

선언적 함수와 익명 함수의 특징

  • 선언함수 : Hoisting의 대상.
  • 익명함수(Anontmous Function) : Hoisting의 대상이 아님.

 

선언적 함수의 단점

  • Hoisting에 의해 덮어쓰기가 됨.

 

 

※ 선언 함수

<body>
    <script>
        
        test();

        function test()
        {
            console.log("test")
        }

        //test
    </script>
</body>

→ Hoisting을 통하여 Execution Context (실행 컨택스트)를 실행한다.

 

※ 익명 함수

<body>
    <script>
        test();

        const test = function()
        {
            console.log("test")
        }
        
        //Uncaught ReferenceError: Cannot access 'test' before initialization
    </script>
</body>

→ Hoisting은 L-Value에 R-Value를 입력하는 것은 인식하지 않는다.

<body>
    <script>
        console.log(a)

        var a = 10
        //undefined
    </script>
</body>

 

 

 

 

선언적 함수와 익명 함수의 혼합사용

  • 1차적으로 익명 함수를 사용하면 에러가 발생한다.
  • ES5의 var를 사용 시 에러가 발생하지 않지만 의도하지 않은 결과가 발생할 수 있다.
  • const 사용 시 (const func1 = …) 에러 발생

 

※ 1차적 익명 함수 사용

<body>
    <script>
        const test = function test()
        {
            console.log("test1")
        }

        function test()
        {
            console.log("test2")
        }

        test();

        //Uncaught SyntaxError: Identifier 'test' has already been declared
    </script>
</body>

 

※ var로 1차적 익명 함수 사용 

<body>
    <script>
        var test = function test()
        {
            console.log("test1")
        }

        function test()
        {
            console.log("test2")
        }

        test();

        //test
    </script>
</body>

 

 

결론

  • 선언 함수 Hoisting에서 덮어쓰기와 수정이 생겨 결론에 오해가 생길 수 있다.
  • 익명 함수와 섞어서 사용할 때 var를 이용해 1차적으로 익명 함수를 필요한 에러가 발생되지 않을 수 있다.
  • 익명 함수로 통일해서 사용하는 것이

 

 

 

 

 

 

 


 

 

 

 

 

 

 

Hoisting

  • 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미한다. 
  • var로 선언한 변수의 경우 Hoisting 시 undefined로 변수를 초기화한다.
  • let과 const로 선언한 변수의 경우 Hoisting 시 변수를 초기화하지 않는다.

 

▶ 예시

* 상단부터 하단까지 순차적으로 Hoisting하면서 Execution Context에 test함수를 덮어 쓴다.
<body>
    <script>
        test();

        function test()
        {
            console.log("test1")
        }

        function test()
        {
            console.log("test2")
        }

        //test2
    </script>
</body>
 

 

 

 

 


 
 

 

* Execution Context(실행 콘텍스트)

출처 : https://velog.io/@stampid/Execution-Context%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8%EB%9E%80

자바스크립트 엔진에서 코드를 실행하기 위해서 실행 가능한 코드를 형상화하고 구분하는 추상적인 개념

 

쉽게 말하자면 코드들이 실행되기 위한 환경이라고 이해하면 될 것 같다.
(코드가 실행된다면 Execution Context 내부에서 실행되고 있는 것이다.)

자바스크립트 엔진에서 코드를 실행하기 위해서는 실행에 필요한 정보를 알고 있어야한다.

  • 변수 : 전역 변수, 지역 변수, 매개 변수, 객체의 프로퍼티
  • 함수 선언
  • 변수의 유효범위
  • this
  1. Execution Context의 종류
    • Global Context(전역 컨텍스트)
      함수 안에서 실행되는 코드가 아니라면 모든 스크립트는 Global Context에서 실행된다.
      스택 구조를 가지는 형태로 Execution Context가 생성이 된 후 global object로 window가 this로 할당되고 스택에 쌓이게 된다.
      Global Context 안에 포함되는 모든 코드들의 실행 가능한 코드들은 순서대로 스택에 쌓이게 되며
      LIFO(Last In First Out)으로 함수를 실행하게 된다.
    • Functional Context(함수 컨텍스트)
      Functional Context는 선언된 함수가 호출이 될 때를 기점으로 생성이 되고,
      함수의 모든 동작이 종료되면 Functional Context는 소멸된다.(closure를 사용한다면 스코프가 소멸하지 않고 이용을 할 수가 있다.)
      각각의 함수들은 각각의 Functional Context를 가지지만 함수가 호출이 되어야만 생성이된다.
  2. Execution Context의 3가지 객체
    실행 컨텍스트는 실행 가능한 코드를 형상화하고 구분하는 추상적인 개념이지만 물리적으로는 객체의 형태를 가지며 3가지 프로퍼티를 소유한다.
    • Variable Object(변수 객체)
      실행 컨텍스트가 생성이되면 위에서 말했듯이 자바스크립트 엔진은 실행에 필요한 정보들이 있기 때문에 정보들을 담을 객체를 생성한다.
      (추측으로는 hoisting과 연관이 있을 것 같다.)
      • variable
      • parameter 와 arguments
      • 함수 선언(함수 표현식은 제외)
      • Variable Object는 실행 컨텍스트의 프로퍼티이기 때문에 값을 갖는데
        전역 코드에서 생성되는 Global Context 와 함수가 호출 될 때 생성되는 Functional Context의 경우 값들이 가리키는 객체가 다르다.
        왜냐하면 Functional Context에는 parameter 와 arguments가 들어 있기 때문에 벌어지는 차이점이다.
    • Scope Chain
      스코프 체인(Scope Chain)은 리스트라고 생각하면 된다.
      전역 객체와 함수의 스코프의 레퍼런스를 저장하고 있다.
      스코프 체인은 실행 컨텍스트가 참조할 수 있는 변수, 함수 선언 등의 정보를 담고 있는 리스트를 가르킨다.
      자바스크립트 엔진은 스코프 체인을 통해 렉시컬 스코프를 파악한다.
      상위 함수, 전역 스코프 등을 참조할 수 있는 이유가 스코프 체인이 검색을 하기 때문이다.
      (하위 -> 상위 -> 전역) 참조에 실패한다면 스코프 체인에 담겨진 순서대로 계속해서 이어가는 것이다.
      검색에 실패하게 된다면 정의되지 않은 변수에 접근하는 것이기 때문에 에러를 발생시킨다.
    • this value
      this 프로퍼티는 this 값이 할당되는데 할당되는 값은
      this의 5가지(global, functionInvocation, (call,apply,bind), Construction, MethodInvocation)패턴으로 결정된다.

 

반응형