호이스팅 & 스코프

Jtiiin:K·2023년 10월 27일
1
post-thumbnail

호이스팅

✅ LexicalEnvironment(1) - environmentRocord(=record)와 호이스팅

개요

  • 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장(=수집)(=record)
  • 수집 대상 정보 : 함수에 지정된 매개변수 식별자, 함수 자체, var로 선언된 변수 식별자 등
  • 컨텍스트 내부를 처음부터 끝까지 순서대로 훑어가며 수집 (실행 X)

호이스팅

  • 변수정보 수집을 모두 마쳤더라도 아직 실행 컨텍스트가 관여할 코드는 실행 전의 상태임
    (=JS 엔진은 코드 실행 전 이미 모든 변수 정보를 알고 있는 것)
  • 변수 정보 수집과정을 이해하기 쉽게 설명한 '가상개념'
    (가상개념 : 실제로는 그렇진 않더라도 사람이 이해하기 쉬운 말로 풀어 표현한 것)

호이스팅 규칙

1. 매개변수 및 변수는 선언부를 호이스팅

// 적용 전
function a (x) {
	console.log(x); // 예상 1
	var x;
	console.log(x); // 예상 undefined
	var x = 2; 
	console.log(x); // 예상 2
}
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); // 1
	console.log(x); // 1
	x = 2;
	console.log(x); // 2
}
a(1);

2. 함수 선언은 전체를 호이스팅

// 적용 전
function a () {
	console.log(b); // 에러 or undefined
	var b = 'bbb';
	console.log(b); // 예상 'bbb'
	function b() { }
	console.log(b); // 예상 fn
}
a();
// 호이스팅 적용
function a () {
	var b; // 변수 선언부 호이스팅
	function b() { } // 함수 선언은 전체를 호이스팅

	console.log(b); // fn
	b = 'bbb'; // 변수의 할당부는 원래 자리에

	console.log(b); // 'bbb'
	console.log(b); // 'bbb'
}
a();

// 함수선언문 -> 함수 표헌식
function a () {
	var b; // 변수 선언부 호이스팅
	var b = function b() { } // 함수 선언은 전체를 호이스팅

	console.log(b);
	b = 'bbb'; // 변수의 할당부는 원래 자리에

	console.log(b);
	console.log(b);
}
a();

3. 함수 선언문, 함수 표현식

함수 정의의 3가지 방식

// 함수 선언문
// 함수명 a가 곧 변수명
// function 정의부만 존재, 할당 명령이 없는 경우
function a () { /* ... */ }
a(); // 실행 ok

// 함수 표현식
// 정의한 function을 별도 변수에 할당하는 경우
// (1) 익명함수표현식 : 변수명 b가 곧 변수명(일반적 case)
var b = function () { /* ... */ }
b(); // 실행 ok

// (2) 기명 함수 표현식
// 변수명은 c, 함수명은 d
// d()는 c() 안에서 재귀적으로 호출될 때만 사용 가능하므로 사용성에 대한 의문(잘 안씀)
var c = function d () { /* ... */ } 
c(); // 실행 ok
d(); // 에러!

함수 선언문을 주의해야하는 이유

💡 함수전체가 호이스팅 되기때문에 코드 전체에 영향을 미치게 됨

// 함수 선언문
// 100번째 줄 : 시니어 개발자 코드(활용하는 곳 -> 200군데)
// hoisting에 의해 함수 전체가 위로 쭉!
function sum (x, y) {
	return x + y;
}

// 5000번째 줄 : 신입이 개발자 코드(활용하는 곳 -> 10군데)
// hoisting에 의해 함수 전체가 위로 쭉!
function sum (x, y) {
	return x + ' + ' + y + ' = ' + (x + y);
}

함수 표현식이었다면?

// 함수 표현식
// 함수 선언부만 위로 쭉!
// 이 이후부터의 코드만 영향을 받아요!
var sum = function (x, y) {
	return x + y;
}

// 함수 선언부만 위로 쭉!
// 이 이후부터의 코드만 영향을 받아요!
var sum = function (x, y) {
	return x + ' + ' + y + ' = ' + (x + y);
}

스코프

✅ LexicalEnvironment(2) - 스코프, 스코프 체인, outerEnvironmentReference(=outer)

스코프

식별자에 대한 유효범위
대부분의 언어에 존재

스코프 체인

식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해나가는 것

outerEnvironmentReference(이하 outer)

스코프 체인이 가능토록 하는 것(외부 환경의 참조정보)


  • outer는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조
    (참조=그 당시의 환경 정보를 저장한다)
  • 예) A함수 내부에 B함수 선언 → B함수 내부에 C함수 선언(Linked List)한 경우
    결국은 타고 타고 올라가서 전역 컨텍스트의 LexicalEnvironment를 참조
  • 항상 outer는 오직 자신이 선언된 시점의 LexicalEnvironment를 참조하고 있으므로, 가장 가까운 요소부터 차례대로 접근 가능
  • 결론 : 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에게만 접근 가능

💡 각각의 실행 컨텍스트는 LE 안에 record와 outer를 가지고 있고, outer 안에는 그 실행 컨텍스트가 선언될 당시의 LE정보가 다 들어있으니 scope chain에 의해 상위 컨텍스트의 record를 읽어올 수 있다.

profile
호기심 많은 귀차니즘의 공부 일기

0개의 댓글