개발공부/자바스크립트

[JavaScript] 스터디 2일차_ 실행컨텍스트

햄❤️ 2021. 6. 16. 21:00
728x90

실행컨텍스트(Execution Context)

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

  - 실행컨텍스트가 활성화되는 시점에 선언된 변수를 위로 끌어올리고(호이스팅), 외부 환경 정보를 구성하는 등의 동작

 

◼ 스택과 큐

 - 스택: 출입구가 하나뿐인 데이터 구조. 즉 먼저 들어간 데이터가 가장 나중에 나오는 구조

 - 큐: 양쪽이 모두 열려있는 데이터 구조. 먼저 들어간 데이터가 먼저 나오는 구조

즉, 실행컨텍스트는 

동일한 환경에 있는 코드들을 실행할때 필요한 환경정보를 모아 컨텍스트를 구성하고 이를 콜 스택에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련있는 코드들을 실행한다. 

 

 동작 순서

 - 처음 자바스크립트 코드를 실행하면, 전역 컨텍스트가 콜 스택에 담기고 함수들이 담긴다. 하나의 함수가 실행되면 콜스택에서 사라지고, 가장 상단에 있던 중단되었던 컨텍스트가 실행이 된다.
 즉, 하나의 실행 컨텍스트가 콜 스택의 맨 위에 쌓이는 순간 = 현재 실행할 코드에 관여하는 시점

 - VariableEnvironment: 담기는 내용은 LexicalEnvironment와 같지만, 최초 실행시의 스냅샷을 유지. 즉 실행 컨텍스트를 생성할 때 여기에 먼저 정보를 담고, 복사하여 LexicalEnvironment를 만듬 

 - LexicalEnvironment : 자바스크립트 코드에서 변수나 함수 등의 식별자를 정의하는데 사용하는 객체로 Environment Record와 Outer Environment Reference를 프로퍼티로 갖는다. 

 - ThisBinding: 식별자가 바라봐야 할 대상 객체. 

 

 EnvironmentRecord

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

호이스팅

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)

//호이스팅
function a() {
	var x = 1;  // 수집대상 1(매개변수)
    console.log(x); //(1) 
    var x; //수집대상 2(변수 선언)
    console.log(x); //(2)
    var x = 2; //수집대상 3(변수 선언)
    console.log(x); //(3)
};

//호이스팅 마친 상태
function a() {
	var x; // 수집대상 1의 변수 선언 부분
    var x;  // 수집대상 2의 변수 선언 부분
    var x;  // 수집대상 3의 변수 선언 부분
    
    x = 1; // 수집 대상 1의 할당 부분
    console.log(x); //(1), 1 출력
    console.log(x); //(2), 1 출력
    x = 2; // 수집대상 3의 할당 부분
    console.log(x); //(3), 2 출력
}
a(1); 

 

변수는 선언부와 할당부를 나누어 선언부만 끌어올리고, 함수 선언은 함수 전체를 끌어올린다. 

//원본코드

function a (){
	console.log(b); // (1)
    var b = "bbb"; // 수집 대상 1 (변수선언)
    console.log(b); // (2)
    function b () {} // 수집 대상 2 (함수선언)
    console.log(b); //(3) 
}

a();

//호이스팅 마친 상태
function a () {
	var b; // 수집대상 1. 변수는 선언부만 
    function b(){} //수집대상 2. 함수 선언은 전체를
    
    console.log(b); // (1)
    b = "bbb"; // 변수 할당부는 제자리에
    console.log(b); // (2)
    console.log(b); // (3)
}
a();

// 호이스팅 - 함수 선언문을 표현식으로 바꿈

function a() {
	var b;
    var b = function b(){}; // 선언문 -> 표현식
    
    console.log(b); //(1) b 함수
    b = "bbb";
    console.log(b); //(2) bbb 출력
    console.log(b); //(3) bbbb 출력
}
a();

 

 함수 선언문과 함수 표현식

- 함수 선언문은 function 정의부만 존재하고 별도의 할당 명령이 없음

 - 함수 표현식은 정의한 function을 별도의 변수에 할당하는 것. 함수명을 정의하면 기명 함수 표현식,
   그렇지 않은 것을 익명 함수 표현식이라고 함. 보통 익명 함수 표현식이 일반적

//함수 정의하는 세 가지 방식

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

// 익명 함수 표현식. 변수명 b가 곧 함수명
var b = function () {}
	b(); //실행o

// 기명 함수 표현식. 변수명은 c , 함수명은 d
// c 함수 내부에서 c() 호출이든 d() 호출이든 잘 됨. 밖에선 d() x
var c = function d () {}
c(); //실행o
d(); //실행x

 

함수 선언문과 함수 표현식의 호이스팅

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

function sum (a,b) {
	return a+b;
}

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

//호이스팅 마친 상태
var sum = function sum(a,b){ //함수 선언문 전체 호이스팅
	return a+b;
};
var multiply; // 함수 표현식은 선언부만 호이스팅 
console.log(sum(1,2)); //3출력
console.log(multiply(3,4)); //multiply is not a function 에러메세지 출력

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

 

◼ 스코프, 스코프 체인

 

 - 스코프: 식별자에 대한 유효범위

 - 스코프 체인: 식별자의 유효범위를 안에서부터 바깥으로 차례대로 검색해 나가는 것.
    식별자를 찾을 때, 일단 자신이 속한 스코프에서 찾고, 그 스코프에 식별자가 없으면 상위 스코프에서 다시 찾아 나감

 * 내부 함수에서는 외부 함수의 변수에 접근 가능하지만, 외부 함수에서는 내부 함수의 변수에 접근할 수 없다.
     모든 함수들은 전역객체에 접근 가능

var x = 1;

function a(){
	console.log(x) // 현재 자신의 스코프에 x가 없지만, 상위 스코프인 전역에서 x를 찾음 = 1 
}
console.log(x); //1 출력
a(); //1 출력

Inner -> Outer -> Global

렉시컬 스코프

스코프는 함수를 호출할 때가 아니라 선언할 때 생긴다. 즉 위치에 따라서 상위 스코프가 결정됨. 정적 스코프라고도 불린다. 

let x = "global";

function a(){
	let x = "local";
    b();
}

//선언당시 전역스코프에 있기 때문에 전역변수인 x를 참조하게 된다.
function b(){
	console.log(x);
}

a(); //global 출력
b(); //global 출력

 

728x90