Execution Context [7] - Hoisting/Closure의 실체 & JS에서 Overloading이 안되는 이유

Marullo·2021년 4월 8일
0
post-thumbnail

Hoisting?

var result = book();
console.log(result); //=> 호이스팅

function book() {
  return "호이스팅";
}

일반적인 스크립팅 언어는 위에서부터 아래로 실행되므로,아직 book()함수의 정의가 안되어 있는 첫번째 줄에서는 에러가 발생한다.
그러나 자바스크립트에서는, 실행 컨텍스트 초기화 단계에 Context의 미리 변수가 저장 된 후에 코드가 실행되기 때문에 식별자 해결이 가능하여 undefined를 출력하거나, 함수 선언문의 경우는 초기화 단계에 미리 Function Object를 생성해두기 때문에 호출까지 가능하다. 이것을 JS의 Hoisting이라고 한다.

다시 Lexical Env를 설정하는 단계를 살펴보자.

어떤 Scope로 엔진 컨트롤이 들어왔다면,(현재의 실행 컨텍스트가 Call Stack에 쌓인 후)
1. 코드를 한 바퀴 돌면서, 선언문을 해석한다.
: 함수 선언문은 초기화 단계에서 Function Object를 생성하여 Context에 저장한다.
2. 코드를 다시 한 바퀴 돌면서, 표현식을 처리한다.
: 모든 표현식은 메모리 공간이 할당되고 이름이 붙여진다. 값은 undefined로 Context에 저장된다.
3. 선언문과 표현식을 모두 처리했다면 코드를 한 줄씩 실행한다.
: book 함수는 선언문으로 이미 function Object가 현재 Scope에 존재하기 때문에 호출이 가능하다.


Hoisting의 실체

Hoisiting이라는 거창한 이름이 있지만,
사실 Context를 초기화를 한 후(실행 환경을 셋팅한 후)에 코드를 실행하는 JS의 특징 덕분에,
코드상에서 아직 선언되어 있지 않은 변수나 함수에 대한 IR(식별자 해결)이 가능하고(물론 값은 undefined가 뜨지만),
심지어 선언문의 경우에는 함수 호출까지 가능한 현상에 그저 Hoisting이란 단어를 붙인 것이다.


[Plus+] JS에서 Overloading이 안되는 이유..

Overloading이란,
함수 이름이 같더라도, 파라미터 수 또는 값의 타입이 다르면 각각의 함수가 존재하는 것이 오버로딩이다. 다른 언어에선 function test(a), funtion test2(a,b)를 다른 함수로 취급한다.

그러나 JS에서는 함수를 {함수명: Function Object} 와 같이 k/v 형태로 선언적 환경 레코드에 저장한다.
Execution Context은 객체다.
우리가 {}객체에 똑같은 key 값을 2개 가질 수 없듯이, 하나의 Execution Context에 함수 이름이 같은 두 개의 다른 Function Object를 가질 수는 없다. 그저 덮어씌워질 뿐이다.




Closure?

Closure는 한 함수에서 "반환되는 함수"다.

그냥 함수를 사용하면 호출될 때 마다 내부 변수들이 초기화된다.
그러나 함수를 반환하는 함수를 사용하면 내부 변수를 유지한 채로, 반환되는 함수는 getter, setter의 역할을 할 수 있다.

function counter(){
  let count = 0
  return function(){
    return ++count
  }
}

adder = counter()
adder() // 1
adder() // 2

Closure의 실체

return function(){ }에서 JS Engine은 function 키워드를 만나자마자 Function Object를 만든다. 이때 Function Object의 내부 프로퍼티 [[Scope]]에 자신을 반환하는 함수의 Scope(즉, 외부 Scope)를 저장해두고 있는다.

이제 반환된 함수가 호출되어 Execution Context를 초기화할 때, 외부 렉시컬 참조에 [[Scope]]에 담긴 외부 Scope를 저장한다.
따라서 Closure 함수는, 자신이 정의된 위치에서 벗어난 영역에서도 외부렉시컬참조에 설정된 변수에 접근이 가능하다. 이렇게 Closure를 이용해서 변수를 캡슐화할 수 있다.

함수가 정의될 때, Function Object의 내부프로퍼티[[Scope]]가 저장되었기 때문에
어디서든 함수가 호출되어도 정의된 위치에 존재하던 변수를 접근할 수 있는 함수가 있다.
Execution Context의 외부렉시컬참조를 적극 이용한 함수를 그저 Closure라 지칭하는 것이다.

profile
한국외대 중국어&컴공 복수전공 - 세미 전공자의 기술 블로그

0개의 댓글

관련 채용 정보