실행 컨텍스트 정리

pyozzi·2025년 2월 27일
0

Javascript

목록 보기
5/7

실행 컨텍스트 객체 (Execution Context)

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

다음과 같은 요소로 구성됨:

1. VE (Variable Environment) → 선언 시점의 LE (Lexical Environment)의 스냅샷

  • record (environmentRecord): 현재 컨텍스트와 관련된 코드의 식별자 정보 저장
  • outer (outerEnvironmentReference): 상위 스코프 참조

2. LE (Lexical Environment) → VE와 동일하지만 변경사항을 실시간으로 반영

  • record (environmentRecord)
  • outer (outerEnvironmentReference)

🔵 record (environmentRecord)

Des: 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장(수집)
매개변수 및 변수는 선언부를 호이스팅 합니다

🔹 변수 및 함수 호이스팅
1) 변수 호이스팅 예제

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

🔹 매개변수 적용 후

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

🔹 호이스팅 적용 후

function a() {
	var x;
	var x;
	var x;

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

📌 변수 선언 (var x)는 호이스팅되지만, 할당(x = 2)은 호이스팅되지 않음

🔹 함수 선언과 함수 표현식의 호이스팅 차이
1) 함수 선언문 (Function Declaration)

console.log(sum(1, 2)); // 정상 실행됨

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

✔ 함수 선언문은 전체가 호이스팅됨 → 정상 실행 가능

2) 함수 표현식 (Function Expression)

console.log(multiply(3, 4)); // ❌ 오류 발생 (변수 선언만 호이스팅됨)

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

✔ 함수 표현식에서는 변수 선언(var multiply)만 호이스팅되고, 함수 할당부는 원래 자리에 남아 있음 → undefined is not a function 오류 발생

📌 협업이 많고 복잡한 코드일수록 함수 표현식을 활용하는 것이 유지보수에 유리함

🔵 outer (outerEnvironmentReference)

Des: outer는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조하며, 항상 outer는 오직 자신이 선언된 시점의 LexicalEnvironment를 참조하고 있으므로, 가장 가까운 요소부터 차례대로 접근 가능

🔹 스코프 체인 예제

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

📌 예상 출력 결과
undefined
1
1
4. this (this binding)

3. this binding -> 현재 실행 중인 컨텍스트에서 this가 가리키는 객체

🔹 전역 공간에서의 this ->
브라우저 환경: window
Node.js 환경: global

🔹 함수와 메서드에서의 this 차이
실행주체가 있으면 메서드(this는 실행주체), 없으면 함수(this는 전역)

화살표함수에서의 this

  • 근데.. 함수를 호출한다고 this가 전역객체가되는 현상.. 흐름이 유실되는 현상...
    (= 함수내부에서 this가 전역객채를 바라보는 문제)
    이를 해결하기 위해 ES6에서는 화살표함수 도입
    --> 화살표함수는 실행컨텍스트가 생성될때 this 바인딩 과정 자체가 없음. 따라서 이전의 값-상위값-이 유지됨.

콜백함수에서의 this

  • 콜백은 함수다.. 따라서 콜백함수에서 this는 전역객체
    단, 예외 존재.. addEventListener 메서드에서 콜백함수 호출시, 자신의 this를 상속

생성자 함수에서의 this

  • 생성자 함수 내부의 this는 새롭개 생성된 인스턴스를 의미

  • 예제

var fullname = 'Ciryl Gane';

var fighter = {
	fullname: 'John Jones',
	opponent: {
		fullname: 'Francis Ngannou',
		getFullname: function () {
			return this.fullname;
		}
	},

	getName: function() {
		return this.fullname;
	},

	getFirstName: () => {
		return this.fullname.split(' ')[0];
	},

	getLastName: (function() {
		return this.fullname.split(' ')[1];
	})()
}

console.log('Not', fighter.opponent.getFullname(), 'VS', fighter.getName()); 
// ✅ Not Francis Ngannou VS John Jones

console.log('It is', fighter.getName(), 'VS', fighter.getFirstName(), fighter.getLastName); 
// ✅ It is John Jones VS Ciryl Gane

📌 분석

  • console.log('Not', fighter.opponent.getFullname(), 'VS', fighter.getName()); // Not, Francis Ngannou , John Jones
    // 1. fighter.opponent.getFullname()는 메서드이고 메서드의 this는 실행주체.
    // 실행주체는 fighter.opponent이고 따라서 이 객체의 프로퍼티인 fullname은 Francis Ngannou
    // 2. fighter.getName()은 fighter의 메서드임으로 this는 fighter. 따라서 this.fullname 은 fighter.fullname John Jones

  • console.log('It is', fighter.getName(), 'VS', fighter.getFirstName(), fighter.getLastName); // It is John Jones VS Ciryl Gane
    // 1. fighter.getName()은 fighter의 메서드 임으로 this는 fighter 따라서 this.fullname 은 fighter.fullname John Jones
    // 2. 화살표 함수는 this binding 안함. 이전의 값-상위값-이 유지됨. 따라서 전역 객체를 가리킴
    // 3. 즉시 실행함수는 호출 주체가 fighter가 아니라 .. fighter.getLastName 부분을 대체했다.. 따라서 이것도 this가 전역객체를 바라봄.

명시적 this 바인딩

🔹 call(), apply(), bind() -> 함수에서 호출할 수 있는 메서드로, 명시적으로 this를 바꿀 수 있다. 함수, 메서드 모두 this 변경 가능

  • call() → 즉시 실행하며 this를 변경

  • apply() → call()과 동일하지만 인수를 배열로 전달

  • bind() → 새로운 함수 반환 (즉시 실행되지 않음)
    넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하는 메서드
    1. 함수에 this를 미리 적용
    2. 부분 적용 함수 구현할 때 용이

var func = function (a, b, c, d) {
	console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); //  window 객체 출력

// call
func.call({ x: 1 }, 4, 5, 6}; // { x: 1 } 4 5 6

// apply
obj.method.apply({ a: 4 }, [5, 6]); // 4 5 6

// ✅ `this`를 명시적으로 설정
var bindFunc1 = func.bind({ x: 1 });
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8

// ✅ 부분 적용 함수 구현
var bindFunc2 = func.bind({ x: 1 }, 4, 5);
bindFunc2(6, 7); // ✅ { x: 1 } 4 5 6 7
bindFunc2(8, 9); // ✅ { x: 1 } 4 5 8 9

Node.js란?

V8 JavaScript 엔진을 기반으로 JavaScript를 실행할 수 있도록 만든 런타임 환경
원래 JavaScript는 브라우저에서만 실행되었지만, Node.js를 통해 서버에서도 실행 가능
런타임 환경이란?
JavaScript 프로그램이 실행되는 환경
예) Node.js 환경(vscode에서 실행), 브라우저 환경(Chrome에서 실행)

profile
코드 한줄마다 의미와 목적을 찾으려고 노력합니다.

0개의 댓글