본문 바로가기
FE/JavaScript

[JavaScript] scope와 var, let, const

by thedev 2022. 10. 25.

 

scope와 var, const, let

 


 

1. 스코프(scope) : 유효범위

 

 변수가 선언되고 나면 그 변수를 사용할 수 있는 범위가 정해져있다. 예를 들어, 함수 내부에서 선언된 변수는 함수 내부에서만 사용할 수 있고 가장 바깥에서 실행된 변수는 어디서든 사용할 수 있다. 이렇게 변수를 참조할 수 있는 유효한 범위를 스코프라고 한다.

 

 

1.1 전역 스코프

 

const text = "hello";
console.log(text); // hello

 

코드의 가장 바깥, 즉 전역에서 선언한 변수는 어디서든 참조할 수 있다.

 

 

1.2 함수 스코프

 

const text = "hello";

function add(){
    const a = 0;
    const b = 1;
    return a + b;
};

console.log(a); // Uncaught ReferenceError: a is not defined
console.log(text); // hello

 

함수 내부에서 선언한 변수는 함수 안에서만 사용할 수 있다. 함수 외부에서 사용하면 참조 에러가 발생한다. 

 

 

1.3 블럭 스코프

 

for(let i = 0; i < 3; i++){
    let num = 0;
    num = num + i;
};

console.log(num); // Uncaught ReferenceError: num is not defined

 

 블럭 안에서 선언한 변수는 블럭 안에서만 사용할 수 있다. 블럭 외부에서 사용하면 참조 에러가 발생한다.

 

 

2. 렉시컬 스코프

 

const x = 1;

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

a(); // 2

 

 함수가 사용될 때, 함수를 어디서 호출했는지가 아닌, 함수가 어디서 선언되었는가를 기준으로 스코프가 결정되는 것이다. const x = 1은 전역으로, const x = 2는 함수 내부에서 사용되었지만 a()를 호출했을 때 x = 2라는 값이 출력된다. x라는 값이 함수의 호출 위치가 아닌 선언 위치를 기준으로 값이 결정되었기 때문이다.

 

 

3. 변수

 

 변수는 var, let, const로 선언할 수 있다.

 

 

3.1 var

 

 var로 변수 선언 및 값의 재할당이 가능하다.

 

var num = 1;
console.log(num); // 1
num = 2;
console.log(num); // 2

 

 그러나 var는 3가지 문제가 있다.

 

console.log(text); // undefined
text = "hello";
var text;

 

 첫번째, var는 호이스팅 된다. var로 코드를 이렇게 작성해도 에러가 나지 않는다. 변수를 선언하기도 전에 값을 할당하는 게 가능하고, 할당 이전에 사용도 가능하다. 값을 할당하기 전에 사용하면 결과값은 undefined로 나오지만 에러가 나오지는 않는다. 이처럼 var는 변수를 어디서 선언하든, var로 선언한 변수는 호이스팅 되어서 어디에서든 사용할 수 있다.

 

for(var i = 0; i < 7; i ++){
   i = i + 1;
};

console.log(i); // 8

 

 두번째, var는 블럭 스코프를 지원하지 않는다. 즉, 블럭 안에서 선언된 변수를 밖에서도 사용할 수 있다.

 

var num = 1;
console.log(num); // 1
var num = 2;
console.log(num); // 2

 

 세번째, var은 같은 이름으로 다시 변수를 선언할 수 있다. 이러한 var의 특징은 개발 중 큰 문제를 만들 수 있기 때문에 ES6부터는 var의 문제를 해결한 let과 const를 사용한다.

 

 

3.2 let

 

 ES6부터는 var 대신 let을 사용한다. let은 블럭 스코프를 지원하기 때문에 var과 달리 아무 곳에서나 사용할 수 없다.

 

console.log(text); // Uncaught ReferenceError: text is not defined
text = "hello";
let text;

 

 let은 값을 재할당할 수 있다. 그러나 같은 이름의 변수를 다시 선언하는 것은 불가능하다.

 

let num;
num = 1;
console.log(num); // 1
num = 2;
console.log(num); // 2
let num = 3; // Uncaught SyntaxError: Identifier 'num' has already been declared

 

 

3.3 const

 

변수 중에서도 값을 변경하지 않는 변수는 const로 선언하는 것이 좋다. const도 블럭 스코프를 지원한다.

 

const num = 1;
console.log(num); // 1
num = 2; // Uncaught TypeError: Assignment to constant variable.

 

 const로 선언된 변수는 값을 변경할 수 없다. 개발 과정에서 값이 변경될 일이 없는 변수는 const로 선언하고, 그 이외의 변수는 let으로 선언해주는 것이 좋다.

 

const name; // Uncaught SyntaxError: Missing initializer in const declaration

 

 const로 변수를 선언할 때는 선언과 동시에 값을 할당해야 한다.

 


 

참고 자료

모던 자바스크립트 Deep Dive 13장

드림코딩님 https://youtu.be/OCCpGh4ujb8

얄팍한 코딩 사전님 https://youtu.be/HsJ4oy_jBx0