실행 컨텍스트 정리

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개의 댓글