Core Javascript #2 실행컨텍스트

Jinmin Kim·2020년 10월 22일
0

실행컨택스트(execution context)

  • 실행컨택스트 : 실행할코드에 제공할 환경정보들을 모아놓은 객체로, 자바스크립트의 동적언어로서의 성격을 잘 파악할수있는 개념
    필요한 환경정보들을 모아 콜스택(call stack)에 쌓아올렸다가,
    가장 위에 쌓여있는 컨택스트와 관련있는 코드들을 실행.
    컨택스트를 구성하는 방법은 전역공간, eval()함수, 함수가 있는데
    흔히 실행컨택스트 구성하는 방법은 함수를 실행하는 것.
var a = 1;
function outer(){
	function inner(){
    	console.log(a); //undefined
        var a = 3;
    }
    inner();
    console.log(a); //1
}
outer();
console.log(a); //1

(관련 이미지)

실행컨택스트에 담기는 정보

VariableEnvironment :

LexicalEnvironment의 내용과 같지만 최초의 실행시에 정보를 유지한다는것이 차이점이며, 이것을 복사하여서 LexicalEnvironment를 만든다.

LexicalEnvironment :

현재의 컨택스트 내부에 a,b,c라는 식별자가있고, 외부에는 d를 참조하게 되어있다. 라는식의 정보가 들어있다.
이 객체 안에는

1) environmentRecord :

현재 컨택스트와 관련된 코드의 식별자 정보가 저장된다.매개변수의 이름, 함수선언, 변수명이 이에 관한 정보이다.
즉 자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다 라고 생각하여도 코드를 해석하는데는 문제가 없다는 말이다. 이것이 호이스팅(hoisting) 즉 끌어올리는 개념이 등장한다.

1-1 : 호이스팅(hoisting)

: 끌어올린다는 의미를 가진 개념으로, 변수정보를 수집하는 과정을 더욱 이해하기 쉬운 방법으로 대체한 가상의 개념.

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

1~3번값을 예상했을때에 호이스팅이라는 개념을 생각하지않으면,
1, undefined, 2라고 나타나는것이 맞지만, 호이스팅 개념을 생각한다면
정답은 1,1,2가 나타난다. 위의 코드를 사용자가 이해하기 쉽게 코드를 변형한다면 아래와같은 코드로 호이스팅 될것이다.
environment는 현재 컨택스트 내의 코드에서 어떤 식별자가 있는지에만 관심이 있고, 어떤값을 할당할지에 대해서는 관심이없다.
그래서 변수명만 위로 끌어올리고, 할당부분은 그대로 남겨둔다.

function a(){
	var x;
    var x;
    var x;
    x = 1;
    console.log(x)
    console.log(x)
    x = 2;
    console.log(x)
}
  • 함수선언 호이스팅
function a(){
    console.log(b); //1)
    var b = 'bbb';
    console.log(b); //2)
    function b(){}
    console.log(b); //3)
}
a();

위의 코드는 그냥 일반적으로 봤을때는 값이
undefined, bbb, Fuction b가 나타날거 같지만
호이스팅을 하고나면

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

가 되어서 값은 Funtion b, bbb, bbb가 나타난다.
그냥 일반 변수의 선언과는 달리 함수선언부는 전체가 다 끌어올려질수있으며, 그앞에 함수명과 같은 변수에 함수를 입력할수있다.

  • 함수선언문과 함수표현식
function a(){} //함수선언문
var b = function (){}; // 함수 표현식

함수선언문과 함수 표현식은 함수를 어떻게 나타내느냐 차이가 있다.
하지만 호이스팅에서는 다르게 작용할수있다.

console.log(sum(1, 2));
console.log(multiply(3, 4));

function sum(a, b){ //함수 선언문 sum
	return a + b;
}

var multiply = function (a, b) { //함수 표현식 multiply
	return a * b;
}

위의 코드를 호이스팅 하게 된다면

var sum = function sum(a, b){ //함수 선언문은 전체를 호이스팅
	return a + b;
    };
  
var multiply; //변수는 선언부만 끌어올리고

console.log(sum(1, 2)); //
console.log(multiply(3, 4)); //

multiply = function(a, b){
	return a * b;
};

sum에 대한 값은 3이 나타나고,
multiply에 대한 값은 호이스팅으로 인해서 multiply is not a function 값이 나타나게된다.

  • let, const 일때에는?
sayHi();
let sayHi = function() {
  console.log("Hi!");
};


ReferenceError: Cannot access 'sayHi' before initialization

let/const 선언은 호이스팅은 되지만, 초기화 전까지는 사용할 수 없는 구간(TDZ)에 위치.
TDZ 안에서 식별자를 참조하면 ReferenceError가 발생.

✅ TDZ(Temporal Dead Zone)란?
1️⃣ 정의: ES6에서 도입된 let/const 변수는 선언 단계에서 호이스팅되지만, 실제 초기화 시점 전까지는 접근이 불가능한 구간이 존재한다. 이를 TDZ라고 한다..

2) outerEnvironmentReference:

EnvironmentRecord를 참조하고 있으며 상위의 스코프체인을 계속해서 참조하고있기때문에 상위의 스코프를 따라 올라가라면 이것을 타고 찾아야한다.

3) ThisBinding :

스코프

: 스코프란 식별자에 대한 유효범위이다. 자바스크립트는 ES5까지는 전역 공간을 제외하면 오직 함수에 의해서만 스코프가 생성된다.
식별자 유효범위안에서 바깥으로 차례로 검색해나가는것을 "스코프체인"이라고 하며 스코프체인을 가능하게 하는것이 LexicalEnvironment와
outerEnvironmentRefernece이다.


위의 그림처럼 outerLexicalEnvironment가 그위의 함수의 EnvironmentRecord를 계속해서 참조하는 형식을 가지게된다.
이러한 구조적으로 인해서 가장 가까운 요소부터 차례대로만 접근이 가능하고 다른순서로 접근을 하는것은 불가능하다. 여러 스코프에서 동일한 식별자를 선언한 경우에는 무조건 스코프 체인상에서 가장 먼저 발견된 식별자에게만 접근이 가능하다.

var a = ;
var outer = function() {
	var inner = function() {
    	console.log(a);
        var a = 3;
    };
    inner();
    console.log(a);
};
outer();
console.log(a);

스코프 체인상에 있는 변수라고 무조건 접근이 가능한것은 아니다.
동일한 이름의 변수를 찾을때에 식별자가 존재하여버리면 그 다음 변수에는 접근이 불가능하다. 이를 변수 은닉화라고 이야기한다.

!!이내용은 코어 자바스크립트(정재남지음) 책을보고 정리한 내용입니다


참고 영상

이해가 아주 잘되는 영상이었습니다.
같이 추천해준, 여러개의 테크톡에 대한 내용들을 이후에도 많이 참고해볼 예정입니다.
https://www.youtube.com/watch?v=EWfujNzSUmw

profile
Let's do it developer

0개의 댓글