[TIL] 8/2

예도리·2021년 8월 3일
1

스코프와 클로저에서 시작된 빙글뱅글 돌아가는,,,TIL

Execution Context

Execution Context(이하 EC)는 스코프(식별자 이름과 값의 매칭)와 기본 객체들(intrinsic objects - Array, Object 등의 기본 생성자와 그 프로토타입 등)을 가지고 있는 Realm 등 코드 수행 환경에 대한 여러 정보를 가지고 있는 어떤 장치라고 생각하면 된다. 결국, EC는 ECMAScript에서 코드 수행(evaluation) 메커니즘을 표현하기 위한 것이며, 실제 스크립트 엔진들은 이 명세와 완벽히 일치하지 않을 수 있다.
NHN Cloud | Execution Context

자바스크립트는 싱글 스레드 환경으로, 코드가 실행될 때마다 Call Stack에 쌓인다. Call Stack 가장 밑에는 global 코드 환경에 대한 EC가 존재한다. 그 위로 함수가 호출될 때마다 EC가 추가되고, return하면 POP되기를 반복한다. 각 시점에서 Stack 최상위에 있는 EC를 running execution context라고 한다.

LexicalEnvironment와 VariableEnvironment

각 EC가 생성되면 변수의 참조를 기록하는 환경인 LexicalEnvironmentVariableEnvironment가 동시에 생성된다. LE와 VE는 초기화 시에 같은 객체를 바라보고 있다.

공통점

  • 변수의 식별자 또는 함수를 저장하는 Environment Record
  • outer environment를 참조하는 outerLexicalEnvironment Reference

차이점

  • VE
    • ER : running execution context 내에서 호이스팅 되는 것(var, 함수선언문) 등 저장
    • OLER : outer environment
  • LE
    • ER : let, const로 선언된 변수, 함수표현식
    • OLER : Variable environment

Hoisting

VE의 Environment Record에 running execution context와 관련된 코드의 식별자 정보(함수선언문, 변수명 등)이 저장되는데, 이 때 context 내부 전체를 훑으면서 순서대로 수집한다. 이 과정을 추상화 한 것이 Hoisting이다! var와 함수 선언부를 최상단으로 올린 후 동작하는 것을 말하는 가상의 개념이다. 물리적으로 일어나지는 않는다.

Scope

ES6부터 Block scope의 등장으로 3가지 타입의 scope가 존재한다.

  • Global scope : global execution context
  • Function scope : function execution context
  • Block scope

scope는 유효 범위이다. 참조 대상 식별자(identifier, 변수, 함수 이름과 같이 구분하여 식별할 수 있는 유일한 이름)을 찾아내기 위한 규칙이다. 식별자가 어디에서 선언되었는지에 따라 다른 유효 범위를 갖는다!
변수는 선언 위치에 의해 스코프를 가지게 된다. 변수가 전역에 선언되었다면 전역 변수가 되고, 코드 어디에서든지 이 변수를 참조할 수 있다. 변수가 함수나 블록 내에서 선언되었다면 지역 변수가 되고, 이 변수는 그 지역과 하부 지역에서만 참조할 수 있다.

Scope Chain

전역 변수와 지역 변수가 중복으로 선언된 경우, 어떤걸 참조할까? 바로 지역 변수를 우선하여 참조한다! Scope Chain 때문에 이런 일이 발생한다.
쉽게 말하면 변수를 검색하는 메커니즘이다. 함수가 중첩되었을 때, 하위 함수 내에서 상위 함수/전역 스코프를 참조할 수 있는데, 이때 스코프 체인을 통해 가능하다. 함수가 중첩될 때마다 상위 함수의 스코프가 하위 함수의 스코프 체인에 포함된다.
함수 실행중에 변수를 만나면 그 변수를 우선 현재 Scope, 즉 Activation Object에서 검색해보고, 만약 검색에 실패하면 스코프 체인에 담겨진 순서대로 그 검색을 이어가게 되는 것이다.

var

ES6부터 Block scope와 함께 let, const의 등장으로 이제는 var 사용이 권장되지 않는다. 이유가 뭘까? 바로 Hoisting 때문이다. 위에서 말했듯이 변수, 함수선언문을 최상단으로 올리는 것을 호이스팅이라고 하는데, var를 사용하면 호이스팅된다. 그러면 변수를 선언하기 전에 사용해도 에러가 발생하지 않는다! 호이스팅으로 인해 마치 선언이 먼저 된 것처럼 동작하기 때문이다. 이런 이유 때문에 문제점이 발생한다. Block 내부에 var를 사용해 변수를 선언하면 호이스팅으로 인해 외부 변수 값도 변하게 된다. 호이스팅으로 인해 선언부분이 전부 최상단으로 올라가고 할당 부분은 그 위치에 남아있는데, 순서에 따라 가장 마지막으로 할당된 값으로 변경된다.
근데 사실은 var 말고 let과 const도 Hoisting이 된다고 한다! 다만, 차이점이 존재한다. var는 호이스팅되고 선언과 undefined로 초기화가 동시에 이루어진다. 반면, let과 const는 선언만 먼저 이루어지고 초기화는 해당 위치에서 이루어진다. 따라서 let과 const는 초기화되기 전에 사용하면 에러가 발생하는 것이다. 1차원적으로 생각하면 어떻게 쓰든 에러가 발생하지 않는 var가 좋은 게 아닌가? 싶기도 하지만, var를 사용하다보면 문제점들이 발생하게 된다.

  • 호이스팅으로 인해 코드가 어떻게 작동될지 직관적으로 예측하기 어려워진다
  • 변수명이 중복되어도 오류가 발생하지 않아서 오류 발견이 어렵다
  • 기존 값이 언제 변경될 지 모른다

등등,,

마무리

간단하게 스코프와 클로저에 대해 검색하고 공부하면 끝날 줄 알았는데, 그 배경에 깔린 내용이 생각보다 엄청 많았다. 그중에 전공 강의에서 배운 내용도 많은데 하나도 기억이 안났다 🥲 그래도 TIL하면서 이해하려고 노력했다. 사실은,, 거의 YIL(yesterday I learned)가 되어버렸는데 그날그날 정리하는 습관을 더 들여야겠다

데브코스 첫 날 소감은

  • 생각보다 장시간 참여하는 게 힘들지는 않았다!
  • 팀이 생겨서 든든하다~
  • 강의를 듣는 게 다가 아니다
  • 정리해서 글을 쓰는 게 쉽지 않다
  • 시간을 좀 더 효율적으로 쓰자
  • 나는 왜 전공 강의를 날려 들었나
  • 다음부터 TIL은 좀 더 간략하게 쓰고 세부적인 내용은 따로 포스트를 쓰는 게 나을 것 같다!

참고

  1. https://cabulous.medium.com/javascript-execution-context-lexical-environment-and-block-scope-part-3-fc2551c92ce0
  2. https://new93helloworld.tistory.com/358
  3. https://meetup.toast.com/posts/123
  4. https://meetup.toast.com/posts/129
  5. https://velog.io/@hotdari90/%EC%8A%A4%EC%BD%94%ED%94%84%EC%B2%B4%EC%9D%B8%EA%B3%BC-%ED%81%B4%EB%A1%9C%EC%A0%80
  6. https://velog.io/@gytlr01/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%A0%89%EC%8B%9C%EC%BB%AC-%ED%99%98%EA%B2%BDLexical-Environment
  7. https://velog.io/@proshy/JSVariable-environment-vs-Lexical-environment

0개의 댓글