javascript

호이스팅, 스코프

에러정리 2021. 9. 26. 19:46

호이스팅이란?

코드가 한 줄씩 순차적으로 실행되는 시점인 런타임 이전에 자바스크립트 엔진에 의해 미리 실행되어 코드의 선두로 끌어올려진 것처럼 동작하는 자바스크립트 고유의 특징을 호이스팅이라고 한다.

var뿐만 아니라 모든 식별자 (let, const, function,class)는 호이스팅 된다. 모든 선언문은 런타임 이전 단계에서 먼저 실행되기 때문

컴파일 타임에 변수, 함수 선언이 메모리에 저장된다. 할당은 코드를 작성한 위치에서 진행된다. 

 

함수 선언 단계

1. 변수선언 : 값을 저장하기 위한 메모리 공간 확보

2. 초기화: 암묵적으로 undifined를 할당해 초기화 한다.

만약 선언하지 않은 식별자에 접근한다면 ReferenceError(참조 에러)가 발생한다.

왜 var만 호이스팅 되는것처럼 보이는가?

var로 선언된 변수의 생명주기

var 키워드로 선언한 변수는 런타임 이전에 자바스크립트 엔진에의해 암묵적으로 "선언단계" 와 "초기화 단계"가 한번에 진행된다. 

let로 선언된 변수의 생명주기

let 키워드로 선언한 변수는 "선언단계" 와 "초기화 단계"가 분리되어 진행된다. 런타임 이전에 자바스크립트 엔진에의해 선언 단계가 먼저 실행되지만 초기화 단계는 변수 선언문에 도달했을 때 실행된다.

스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 일시적 사각지대라고 부른다. 

 

함수 선언문

function add(x , y) {
	return x + y;
}

함수 선언문으로 정의한 함수는 런타임 이전에 함수 객체가 생성된다. 자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 생성된 함수 객체를 할당한다.

즉, 코드가 한줄씩 순차적으로 실행되는 시점인 런타임에는 이미 함수 객체가 생성되어 있고 함수 이름과 동일한 식별자에 할당까지 완료된 상태 -> 함수 선언문 이전에 함수를 참조, 호출할 수 있다.

참조 O 호출 O

함수 표현식

var sub = function (x, y) {
	return x - y
}

함수 표현식은 변수 선언문과 변수 할당문을 한번에 기술한 축약 표현

변수 선언은 런타임 이전에 실행되어 undefined로 초기화

변수 할당문의 값은 런타임에 평가되므로 함수 표현식의 함수 리터럴도 할당문이 실행되는 시점에 평가되어 함수 객체가 된다. (할당은 호이스팅 x)

참조 O(undefinde) 호출 X

함수 호이스팅은 함수를 호출하기 전에 반드시 함수를 선언해야 한다는 당연한 규칙을 무시한다. 함수 선언문 대신 표현식을 사용할것을 권장한다.

스코프란?

자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효범위

스코프(유효 범위)를 통해 식별자인 변수 이름의 충돌을 방지하여 같은 이름의 변수를 사용할 수 있게 한다.

즉 스코프는 네임스페이스이다.

 

스코프의 종류

전역스코프 - 코드의 가장 바깥 영역 <전역변수>

지역스코프

스코프   설명 변수  
전역 스코프   코드의 가장 바깥 영역 전역 변수 어디서든 참조가능
지역 스코프   함수 몸체 내부 지역변수 자신의 지역스코프, 하위 지역 스코프에서 유효
함수 스코프 함수만을 지역스코프로 인정   var
블록 스코프 중괄호안에 지역 스코프   let, const

렉시컬 스코프 - 함수를 어디서 호출했는지가 아니라 어디서 정의했는지에 따라 상위 스코프를 결정한다.

var x = 'global';

function foo() {
	console.log(x); // 1undefined
    var x = 'local';
}

foo();
console.log(x); //global

foo 함수 내부에서 선언된 지역 변수 x는 1의 시점에서 이미 선언되었고, undefined로 초기화되어있다.

따라서 전역변수 x를 참조하는 것이 아니라 지역변수 x를 참조한다. 

전역변수의 생명주기는 전역 객체의 생명주기와 같다. 생명주기가 길면 메모리 리소스도 낭비된다.

모든 코드가 전역변수를 참조하고 변경할 수 있는 암묵적 결합을 허용하게 된다.

변수의 유효범위가 클수록 코드의 가독성은 나빠지고 의도치 않게 상태가 변경될 수 있는 위험성도 높아진다.

호이스팅은 스코프 단위로 동작한다.