01. 실행 컨텍스트란?

실행할 코드에 제공할 환경 정보들을 모아놓은 객체

  • VariableEnvironment: 현재 컨텍스트 내의 식별자들 정보 + 외부 환경정보, LexicalEnviornment의 스냅샷
  • LexicalEnvironmnet: VariableEnvironment와 같지만 변경사항이 실시간으로 반영됨
  • ThisBinding: this 식별자가 바라봐야할 대상 객체

02. VariableEnvironment

실행 컨택스트를 생성할때 VariableEnvironment에 정보를 먼저 담고, 이를 복사해서 LexicalEnvironmnet를 만든다

03. LexicalEnvironment

수시로 변경하는 환경 정보

2-3-1 environmentRecord와 호이스팅

environmentRecord: 현재 컨택스트와 관련된 코드의 식별자 정보가 저장됨

//매개변수 식별자
    var a = 1;
    let b = 1;
    const c = 4;
    var meta = {
    	content:2,
    	props: "string"
    }
//함수 선언자
function a() {} //함수 선언문

호이스팅 규칙

코드가 실행되기 전에 엔진에서 환경에 사용된 변수 명을 수집(이해하기 쉽게, 변수를 최상단으로 끌어 올린다고 생각)

같은 컨택스트 내 선언된 변수, 함수를 hoisting 하고, 할당 시점에 해당 변수/함수를 할당한다.

function a(){
	console.log(b); //function b
	var b = 'bbb'
	console.log(b); //'bbb'
	function b(){/* */}
	console.log(b); //'bbb'
}

2-3-2 스코프, 스코프 체인, outerEnvironmentReference

함수스코프: ES5에서는 함수에 의해서만 스코프가 생성됨; var

블록스코프: ES6에서는 블록에 의해서도 스코프 경계가 발생됨; let, const, class, strict mode

스코프 체인: 식별자 유효범위 안에서부터 바깥으로 차례로 검색해 나가는 것

아래와 같이 outer 함수 안에 inner 함수가 호출된 경우, inner함수의 outerEnvironmentReference는 outer함수의 LexicalEnvironment을 참조함

→ 무조건 스코프 체인상에서 가장 먼저 발견된 식별자에만 접근 가능함

var a = 1;
var outer = function(){
	var inner = function(){
		// var a = 3; (1)
		console.log(a) // (결과)
		var a = 3; (2)
	}
	inner();
	console.log(a)
}
outer();
console.log(a) 
  • (1) 처럼 선언과 할당이 (결과)보다 위에 있을 경우엔, "3" 이 출력됨
  • (2) 처럼 hoising으로 선언은 먼저 되고 (결과) 보다 할당이 나중에 될 경우 "undefined" 가 출력됨
  • 만약 (1), (2) 가 주석 처리 되고, inner함수 컨텍스트에 a변수가 없는 경우: 스코프 체이닝을 통해 global 객체까지 해당 변수를 찾음
    • inner함수 LexicalEnvironment의 environmentRecord에서 a 변수를 서치 → 없다면 아래 로직
    • inner함수 LexicalEnvironment의 outerEnvironmentReference 즉, outer 함수의 LexicalEnvironment에서 a 변수를 찾음 → 없다면 아래 로직
    • outer함수 LexicalEnvironment의 outerEnvironmentReference 즉, global 객체의 LexicalEnvironment에서 a 변수를 찾음 → 없다면 "undefined"
    • 이 경우에는 (결과)에서 "1" 이 출력됨

변수은닉화(variable shadowing): inner함수에서 a 변수를 선언함으로써 전역 공간의 a 변수 접근을 막음

var name = 'a';

function a(){
	console.log(name) // a가 찍힘.. 함수 선언식이어서 outerEnvironmentVariable 이 전역임
}

function b(){
	name = 'b'
	a()
}

b();

04. this

thisBinding에는 this로 지정된 객체가 저장됨. 실행 컨택스트 활성화 당시에 this가 지정되지 않은 경우, this는 전역 객체가 저장됨.

05. 정리

  • 실행 컨텍스트
    • 현재 실행할 코드에 바라보아야 할 환경 정보를 담고 있는 객체
  • LexicalEnvironment
    • 수시로 변경되는 환경 정보를 담은 객체
    • environmentRecord
      • 현재 컨텍스트에서 바라보아야할 식별자 정보를 담고 있는 객체
      • Hoisting
        • 코드 실행 전에 자바스크립트 엔진이 컨텍스트에서 변수명을 수집하는 것
    • outerEnvironmentReference
      • 현재 컨텍스트가 호출된 시점의 컨텍스트를 담고 있는 레퍼런스를 담고 있는 객체
      • 스코프 (scope)
        • 식별자에 대한 유효 범위
        • 함수 스코프(function scope)
          • ES5 에서 함수에 의해서만 스코프가 생김: var
        • 블록 스코프(block scope)
          • ES6 에서 블록에 의해서도 스코프가 생김: let, const, class, Strict mode
      • 스코프 체이닝(scope chaining)
        • 현재 scope, 컨텍스트에서 식별자를 찾을 수 없는 경우 outerEnvironmentReference를 통해 상위 스코프, 컨텍스트에서 식별자를 찾아 가는 방식
        • 변수 은닉화(variable shadowing)
          • 스코프 체이닝의 특성을 이용해, 자식 컨텍스트에 전역 변수 명과 동일한 변수를 선언함으로써 전역 변수 접근을 막는 방식
  • 함수 선언식
    • 실행 컨텍스트가 수집될 때 함수 그 자체가 호이스팅 됨
    • 지양하자
  • 함수 표현식
    • 실행 컨텍스트가 수집될 때 선언부만 호이스팅 되고, 할당 시점에 함수가 할당됨

06. 궁금한것

  • VariableEnvironment 은 어디에 사용되는가?
    • es5 → var에 대한 정보, es6 → let, const ...
  • 함수 선언식과 표현식을 같이 쓰는 경우에는 호이스팅이 어떻게 되는가? sum 변수는 선언/할당, new_sum은 선언부만 hoisting 됨?
	var new_sum = function sum(){/* */}
  • 콜백 함수의 컨텍스트는 어떻게 되는가?
profile
Frontend engineer

0개의 댓글