책 읽다가 코딩하다 죽을래

자바스크립트 scope 본문

코딩/자바스크립트

자바스크립트 scope

ABlue 2021. 7. 20. 17:07

 

scope는 어떤 하나의 데이터가

어느 정도의 범위를 가져 영향을 주는지의 대한 개념이다.

 

function fn(){
	int a = 1;
}
fn();
system.out.println(a);

 

자바나 c++을 배웠다면

위의 코드가 이상하다고 생각할 것이다.

왜냐하면 함수 밖에서 함수 안에 있는 a를 접근하면 분명 오류가 일어나기 때문이다.

 

즉 함수 안에서 선언된 a는 밖에서 접근할 수 없는 것

a의 scope는 함수 fn 범위 안이라고 정의할 수 있다.

 

자바스크립트에서의 scope는 다양해서 헷갈릴 것이다.

이번 시간에 자세히 알고 가자.

 

 

자바스크립트 내에 데이터 타입은 크게

var, let, const로 나뉜다.

여기서 let과 const는 스코프가 같으니

var와 let, const 이렇게 설명하겠다.

 

 


var scope


더보기

1. var의 스코프는 함수 수준 스코프를 가진다.

function fn(){
	name = "ablue";
    console.log(name);
	var name;
}

 

  

 위의 코드처럼 

선언하기 이전에도 사용할 수 있다.

 

왜냐하면 자바스크립트 엔진이 fn의 함수를 실행하게 되면

실행하기 전에 fn 함수 안에 있는 모든 var 변수를 찾아서

실행 컨텍스트에 집어넣은 후 변수에 필요한 메모리를 미리 할당하기 때문이다.

그래서 선언하기 전에도 사용할 수 있다.

그런데 선언만 호이스팅이 되고 할당하는 것은 호이스팅이 되지 않는다.

 

function fn(){
    console.log(name);
    name = "ablue";
	var name;
}

 

이런 식이면 콘솔에는 undefined가 뜬다.

name이란 변수는 있는데 값은 할당되기 이전이기 때문이다. 

 

 

 

2. var는 재선언이 가능하다.

 

function fn(){
	var name = "ablue";
	var name = "red";
    console.log(name);
}
fn();

 

var는 재선언이 가능하므로

이런식의 코드는 already define 오류가 일어나지 않으며 정상 작동된다.

콘솔에선 최근 초기화됐던 red가 표시된다.

 

 

 

 

이런 말도 안 되는 스코프 방식으로 인해 개발자들은

var로 인해 오류가 일어나면 찾기가 힘들어서

var보다 let을 선호한다.

 

 

 


const, let scope


 

 

더보기

1. let과 const는 재선언이 불가능하다.

function fn(){
	const a = 1;
    const a = 2;	// Uncaught SyntaxError: Identifier 'a' has already been declared
}

 

 

2. const와 let은 block 수준 스코프를 가진다.

 

여기서 block 뭐냐 하면 {}를 말한다.

 

function fn(){
	const ary = [1,2,3];
    console.log(i);		// Uncaught ReferenceError: i is not defined
    for(let i = 0; i < ary.length; i++){
        console.log(ary[i]);
    }
}
fn();

 

for 구문 block 안에서 선언된 i는

for 구문 block 밖에서는 사용될 수 없다.

 

그런데 이 상황을 보자

 

 

function fn(){
    console.log(i);		// Uncaught ReferenceError: Cannot access 'i' before initialization
    let i  = 1;
}
fn();

 

이 코드도 위쪽의 코드처럼 안 되는 것은 뻔히 알고 있다.

근데 아직 i 선언 전이니까 is not defined 오류가 일어나야지

i 선언 전엔 접근할 수 없다는 레퍼런스 오류가 나고 있다.

 

그렇다. 자바스크립트 엔진은 let, const 선언 전에도 그 존재를 알고 있다.

여기서 TDZ라는 중요한 개념이 등장한다.

 

 


TDZ(Temporal Dead Zone) 일시적 사각지대


 

더보기

let과 const도 호이스팅이 된다.

자바스크립트 엔진은 함수가 시작하면

함수 내에 var 뿐만 아니라 let과 const도 찾아내어

호이스팅을 하여 실행컨텍스트에 집어넣는다.

 

하지만 선언한 후, 초기화 단계에서 메모리를 확보하는데

let과 const는 초기화 전까지는 메모리에 공간을 확보하지 않는다.

(var는 선언하자마자 메모리에 공간을 확보합니다.)

그래서 호이스팅이 되어 is not defined 에러는 나지 않고

변수가 참조하는 메모리를 찾지 못해 레퍼런스에러가 일어난다.

 

정리하자면 let, const는 호이스팅이 되지만

선언 전까지는 TDZ 상태가 되는 것이다.

TDZ 상태에서는 액세스를 하지 못한다.

 

function fn(){
    console.log(i);		// 자바스크립트 엔진 : ? i라는 변수는 있는데 얘가 참조한 메모리가 없는데??
    let i  = 1;
}
fn();

 

사실상 let, const를 사용할 때는 이전 c++, 자바, 파이썬을 사용할 때처럼

생각하면서 코드를 짜도 문제는 없다.

 

하지만 이 개념을 알아야 하는 이유는 작동 원리도 알아야 고수가 될 수 있는 것이고 면접에서도 물어보기 때문이다.

 

 

 

여기까지 읽으셨으면 한 번 이 코드를 출력 결과를 미리 생각해보고 출력해보자.

 

function scope(){
	const a = 0;
	let b = 0;
	var c = 0;

	if(a === 0){
		const a = 1;
		let b = 1;
		var c = 1;
		console.log(a, b, c);
	}
	console.log(a, b, c);
}

 

 

 

 

출력 결과

더보기
출력 결과