[코어 자바스크립트] 02. 실행 컨텍스트

jjune095·2021년 3월 17일
0
post-thumbnail

02. 실행 컨텍스트

실행 컨텍스트란?

  • 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
    ⇒ call stack에 쌓기 ⇒ 코드의 실행 흐름
  • 자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념
  • 어떤 실행 컨텍스트가 활성화되는 시점에 선언된 변수를 위로 끌어 올리고(hoisting), 외부 환경 정보를 구성하고, this 값을 설정한다.

실행 컨텍스트 순서

  • 구성하는 방법으로는 전역공간, eval(), 함수가 있다.
// 전역 컨텍스트 -- (1) 번으로 실행
var a =1;
function outer(){
	function inner(){
	..	
	}
	inner();  --- (3) 번으로 실행
}
outer() ---- (2)번으로 실행. 

Stack에는 1 → 실행 -> 2 → 실행 -> 3 이 쌓이게 되고 3 -> 2 -> 1 순으로 stack에서 빠진다.

환경 정보 수집

컨텍스트가 활성화될 때 자바스크립트 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는데 필요한 환경 정보들을 수집해서 실행 컨텍스트 객체에 저장한다.

  • VariableEnvironment : 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보. 선언 시점의 LexicalEnvironment의 스냅샷으로, 변경 사항은 반영되지 않음.
  • LexicalEnvironment : 처음에는 VariableEnvironment와 같지만 변경 사항이 실시간으로 반영됨.
  • ThisBinding : this 식별자가 바라봐야 할 대상 객체.

environmentRecord와 호이스팅

  • environmentRecord에 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장된다. 컨텍스트를 구성하는 함수에 지정된 매개변수 식별자, 선언한 함수가 있을 경우 함수 자체, var로 선언된 변수의 식별자.

  • environmentRecord는 현재 실행될 컨텍스트의 코드 내에서 어떤 식별자가 있는지만 관심이 있고 어떤 값이 할당될 것에는 관심이 없다.

  • 순서대로 수집한다.

  • 코드가 실행되기 전에 자바스크립트 엔진은 이미 환경에 속한 코드의 변수명을 모두 알고 있다. ⇒ 이는 호이스팅을 할 수 있게 해줌.

  • 자바스크립트 엔진이 식별자들을 최상단으로 끌어올려 놓는다.

호이스팅 규칙

function a (x) { // 수집 1
	console.log(x); -- 1
	var x;  // 수집 2
	console.log(x)  -- 2
	var x=2 // 수집 3
	console.log(x)  -- 3
}
a(1)

우리가 예상하기로는 1,undefined,2가 출력될 것이라고 예상하지만 호이스팅이 일어나게 되어 1,1,2 라는 결과가 나온다.

// 실제가 아닌 엔진 변환 예시
function a (x) {
	var x;  // 수집 1
	var x;  // 수집 2
	var x;  // 수집 3

	x=1;
	console.log(x); // 1
	console.log(x)  // 1
	x=2 
	console.log(x)  // 2
}

함수 호이스팅

함수가 있으면 함수도 hosting 된다.!

// 호이스팅 적용 전
function a() {
    console.log(b);           // (1)
    var b = 'bbb';            // 수집 대상 1 (변수 선언)
    console.log(b);           // (2)
    function b() {            // 수집 대상 2 (함수 선언)
        console.log(b);       // (3)
    }
}
a();

위의 예는 어떨까?

(1)은 undefined, (2)는 bbb, (3)은 b 함수가 출력될 것 같다.

// 호이스팅이 적용됐다고 가정.
function a() {
    var b;
    var b = function b () { } // 바뀐 부분
    
    console.log(b); // (1) 함수 b
    b = 'bbb';
    console.log(b); // (2) bbb
}
a();

함수의 할당 부분이 최상단으로 끌어올려진 부분이다. 이와 같이 함수 선언은 전체를 최상단으로 끌어올린다.

🌟 함수 선언식과 표현식 🌟

function a () { } // 함수 선언문. 함수명 a가 곧 변수명

const b = function () {} // (익명)함수 표현식 변수 b가 곧 함수명

함수 선언방식은 순서와 상관없이 함수 전체가 hosting 되기 때문에 함수 호출보다 늦게 선언되어도 문제가 없다.

단, 나중에 같은 이름으로 함수가 선언될 경우 나중에 선언된 함수가 첫번째 함수를 덮어 씌우기 때문에 문제가 발생한다. (더더욱 에러도 발생하지 않음... ⇒ 매우 위험)

따라서, 함수 표현식으로 선언한 방법이 안전하다. 단, 호출을 하기 전에 반드시 선언을 해줘야 한다. !!!

스코프, 스코프 체인

스코프(scope)

전역 스코프 (Global scope)
코드 어디에서든지 참조할 수 있다.

지역 스코프 (Local scope or Function-level scope)
함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.

지역 스코프는 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다.

단, ES6에서는 블록 레벨 스코프를 사용 가능하다. ES5 var는 적용이 안되고 const, let, class, strict mode에서만 범위가 구분된다.

 var x = 0;
{
  var x = 1;
  console.log(x); // 1
}
console.log(x); // 1

let y = 0;
{
  let y = 1;
  console.log(y); // 1
}
console.log(y); // 0

스코프 체인

식별자의 유효범위를 안에서부터 바깥으로 차례로 검색하는 것. (outerEnvironmentReference에 의해 가능해진다.)

  • 여러 스코프에서 동일한 식별자를 선언한 경우 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능하다.

  • outer 함수 내부에서는 outer 및 전역 변수만 접근가능하고 inner 스코프 내부에서 생성된 변수에는 접근하지 못한다.

  • inner 함수 내부에서는 inner, outer ,전역 스코프 모두 접근 가능하다.

// 스코프 체인 예제
var a = 1;
var outer = function () {
  var inner = function () {
    console.log(a);
    var a = 3;
  };
  inner();
  console.log(a);
};
outer();
console.log(a);

스코프 체인이란 식별자가 현재 컨텍스트에 없다면 outerEnvironmentReference 를 통해 외부의 컨텍스트에 있는지 알아보며, 있다면 해당 식별자를 사용할 수 있도록 동작을 한다.


  • 전역 변수 사용을 최소화하여 코드의 안전성을 높이는 것이 좋다.
  • this는 지정되지 않는 경우 전역 객체가 저장되고 (window) 실행 컨텍스트를 활성화하는 당시에 지정된 this가 저장된다. 함수를 호출하는 방법에 따라 그 값이 달라진다.

References
위키북스 코어자바스크립트 도서, 정재남 지음

profile
프론트엔드 개발자 남준영입니다.

0개의 댓글