[코어자바스크립트] - 2장. 실행 컨텍스트

sypaik-dev·2023년 4월 13일
0
post-thumbnail

실행 컨텍스트란?

Stack과 Queue

실행 컨텍스트
실행할 코드에 제공할 정보들을 모아 놓은 객체

실행 컨텍스트의 동작
1) 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트 구성
2) 컨텍스트들을 call stack에 쌓아 올려둠
3) 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행
4) 전체 코드의 환경과 순서 보장

// ------------------------- (1)
var a = 1;
function outer() {
	function inner() {
    	console.log(a);
      	var a = 3;
// ------------------------- (2)
    }
  inner();// --------------- (3)
  console.log(a);
// ------------------------- (4)
}
outer();
// ------------------------- (5)
console.log(a);
// ------------------------- (6)

실행순서는 (1) - (5) - (3) - (2) - (4) - (6)

💡 코드 실행 과정
1. 코드를 실행하는 순간 (1) 전역 컨텍스트가 콜 스택에 담긴다
2. 함수 호출문 outer()을 만나는 순간 해당 함수를 콜 스택에 추가한다.
3. 추가된 함수의 내부로 이동하여 코드들을 순차적으로 실행한다.
4. (3)에서 inner 함수의 실행 컨텍스트가 콜 스택의 최상단에 담기면 outer 컨텍스트와 관련된 코드의 실행을 중단하고 inner 함수 내부의 코드를 순차적으로 진행한다.
❗모든 코드가 콜스택에 처리되었으면 선입후출(FILO, First In Last Out)로 콜스택에서 실행한다.
5. 실행이 완료된 코드는 콜 스택에서 제거되고 아무것도 남지 않은 상태로 종료된다.

활성화된 실행 컨텍스트의 수집 정보

  • VariableEnvironment

    • environmentRecord (snapshot)
    • outerEnvironmentReference (snapshot)
  • LexicalEnvironment

    • environmentRecord
      : 함수 안의 코드가 실행되기 전에 현재 컨텍스트와 관련된 코드의 식별자 정보가 저장
    • outerEnvironmentReference
  • ThisBinding

LexicalEnvironment

environmentRecord와 호이스팅

호이스팅

  • 호이스팅(hoisting): hoist(끌어 올리다) + ~ing ➡️ 식별자들을 최상단으로 끌어 올려놓자
  • 코드가 실행되기 전임에도 자바스크립트 엔진은 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있음 (자바스크립트 엔진은 식별자들을 최상단으로 끌어 올려 놓은 다음 실제 코드를 실행하는 것으로 생각해도 코드 해석에 문제 없음)

매개변수와 변수에 대한 호이스팅

  • environmentRecord는 현재 실행될 컨텍스트 대상 코드 내에 어떤 식별자들이 있는지에만 관심이 있지, 각 식별자들이 어떤 값이 할당될지에는 관심이 없음

매개변수와 변수에 대한 호이스팅(1)

function a (x) {     // -- 수집대상 1 (매개변수)
	console.log(x); // (1)
  	var x;          // -- 수집대상 2 (변수 선언)
  	console.log(x); // (2)
  	var x = 2;	    // -- 수집대상 3 (변수 선언)
  	console.log(x); // (3)
}
  • 출력 결과: 1, 1, 2

매개변수와 변수에 대한 호이스팅(2)

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)
}

a();
  • 매개변수를 변수 선언 및 할당과 같다고 간주하여 반환

매개변수와 변수에 대한 호이스팅(3)

function a () {
	var x;  // --------- 수집 대상 1(매개 변수)의 변수 선언 부분
  	var x;  // --------- 수집 대상 2의 변수 선언 부분
  	var x;  // --------- 수집 대상 3의 변수 선언 부분
  	x = 1;  // --------- 수집 대상 1의 할당 부분
  	console.log(x); //   (1)
  	console.log(x); // 	 (2)
  	x = 2;  // --------- 수집 대상 3의 할당 부분
  	console.log(x); // 	 (3) 
}
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 b() {}, bbb, bbb

함수 선언의 호이스팅(2)

function a() {
	var b; // ------------ 수집 대상 1(변수 선언)의 선언 부분
  	function b() {} // --- 수집 대상 2(함수 선언)의 전체
  	console.log(b); // --- (1)
  	b = 'bbb'; // -------- 수집 대상 1의 할당 부분
  	console.log(b); // --- (2)
  	console.log(b); // --- (3)
}
a();

함수 선언문과 함수 표현식

  • 함수 선언문: function 정의부만 존재하고 별도의 할당 명령이 없는 것

    • 반드시 함수명이 정의되어 있음
    • 호이스팅 시 함수 전체를 끌어 올림
  • 함수 표현식: 정의한 함수를 별도의 변수에 할당하는 것

    • 익명 함수 표현식: 함수명을 정의하지 않음

    • 기명 함수 표현식: 함수명을 정의함

      • 외부에서 함수명으로 호출 불가능
      • 함수 내부에서 재귀함수를 호출하는 용도로 함수명을 쓸 수 있음
      • 호이스팅 시 변수로 취급되어 선언 부분만 끌어 올림
function a() { /* ... */ } // 함수 선언문. 함수명 a가 곧 변수명
a(); // 실행 가능

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

var c = function d() { /* ... */ } // 기명 함수 표현식. 변수명은 c, 함수명은 d
c(); // 실행 가능
d(); // 실행 불가능. 에러!

함수 선언문의 위험성

  • 함수 선언문이 코드 상단에 선언되어 있는 상태에서 동일한 이름의 함수 선언문이 코드 하단에 중복해서 선언될 경우
  • 호이스팅 과정에서 두 함수 선언문이 모두 끌어 올려지고, 상대적으로 하단에 있는 함수 선언문이 코드 전체에 영향을 미치게 된다.
  • 함수 표현식으로 함수를 사용한다면 하단의 함수가 나오기 전까지는 상단에 선언된 함수로 사용되다가 하단의 함수가 나오면 그때부터 하단의 함수로 적용된다.

함수 선언문 예제

console.log(sum(3, 4)); // (1) : 7을 기대하지만, 3 + 4 = 7이 출력

function sum(x, y) { // -- 상단 함수
  return x + y;
}

var a = sum(1, 2);
console.log(a); // ------- (2) : 3을 기대하지만, 1 + 2 = 3이 출력

function sum(x, y) { // -- 하단 함수
  return `${x} + ${y} = ${x + y}`;
}

var c = sum(1, 2);
console.log(c); // ------- (3) : 1 + 2 = 3이 출력

함수 표현식 예제

// console.log(sum(3, 4)); // (1) : sum의 값이 없어서 undefined를 반환하기 때문에 에러! 

var sum = function (x, y) { // -- 상단 함수
  return x + y;
}

var a = sum(1, 2);
console.log(a); // ------- (2) : 3 출력

var sum = function (x, y) { // -- 하단 함수
  return `${x} + ${y} = ${x + y}`;
}

var c = sum(1, 2);
console.log(c); // ------- (3) : 1 + 2 = 3이 출력
profile
Frontend Developer

0개의 댓글

관련 채용 정보