변수(variable)란 데이터(data)를 저장할 수 있는 메모리 공간을 의미하며, 그 값이 변경될 수 있다.
변수는 코드에서 중요한 역할을 맡고 있다. 변수가 없다면 일일히 값을 직접 입력하거나 하나하나 바꿔야할 것이다.
자바스크립트에서는 var, let, const 키워드를 사용하여 '변수'를 선언한다.
ES5까지는 var 키워드만 사용되었는데, ES6부터는 let과 const라는 키워드가 생겼다.
그렇다면 왜 자바스크립트는 변수를 만들 때 var와 let, const 중 하나를 선택하게 해두었을까?
var | let | const | |
Global Scope | yes | no | no |
Script Scope | no | yes | yes |
Function Local Scope | yes | yes | yes |
Block Scope | no | yes | yes |
재선언 | yes | no | no |
재할당 | yes | yes | no |
출처 : 생활코딩 JavaScript - var VS let VS const
var, let, const 차이점
var, let, const의 차이점을 정리해보면 다음과 같다.
- 변수 스코프의 유효범위
- 변수 호이스팅 방식
- 전역객체 프로퍼티 여부
- 재선언 가능 여부
- 재할당 가능 여부
#1. 변수 스코프의 유효범위
스코프란 변수에 접근할 수 있는 유효 범위를 뜻한다. 예를 들어, 함수 내부에서 선언된 변수는 함수 내부에서만 참조가 가능하다.
자바스크립트는 var 로 선언한 변수의 스코프와 let, const로 선언한 변수의 스코프가 다르다.
글로벌 스코프 (Global Scope)와 스크립트 스코프 (Script Scope)
var v0 = "v0";
let l0 = "l0";
console.log(v0, l0); // v0, l0
var로 선언한 변수는 '전역 변수'로 취급이 되서 Global Scope를 갖게 되고, let과 const로 선언한 변수는 '지역 변수'로 취급이 되서 Script Scope를 갖는다.
자바스크립트는 일단 Scope의 가장 위에 있는 Script Scope을 조회해서 변수의 값을 찾는다. 그리고 값을 찾지 못한 변수는 Global Scope을 조회해서 찾은 후 화면에 출력한다.
함수 레벨 스코프(function-level scope)
function fn() {
var v1 = "v1";
let l1 = "l1";
console.log(v1, l1);
}
fn(); // v1, l1
console.log(v1); // ReferenceError: l1 is not defined
console.log(l1); // ReferenceError: l1 is not defined
함수 내부에서의 상황은 달라진다. 함수 내부에 선언된 변수 var는 '지역 변수'로 취급이 된다.
그래서 위의 코드에서처럼 함수 내부가 아닌 외부에서 참조하려고 하면 에러가 발생한다. let과 const 역시 마찬가지로 함수 외부에서 참조할 수 없다.
함수 내에서 var, let, const로 선언한 변수들은 Local Scope를 갖기 때문이다.
블록 레벨 스코프(block-level scope)
* 블록은 if문, for문 등에서 중괄호 { }로 둘러싸인 코드 영역을 말한다.
if(true) {
var v2 = 'v2';
let l2 = 'l2';
console.log(v2, l2); // v2, l2
}
console.log(v2); // v2
console.log(l2); // ReferenceError: a is not defined
하지만, var로 선언한 변수는 함수를 제외한 모든 영역에서 '전역 변수'로 취급이 되어 Global Scope를 갖는다. 조건문, try/catch문 등의 코드 블럭{...} 내부에서 var로 선언된 변수를 전역 변수로 간주한다.
그러나 let과 const는 함수 내부는 물론, if문이나 for문 등의 코드 블럭{ ... } 에서 선언된 변수도 지역변수로 취급한다. 그래서 if문 블럭 내부에서 let, const로 선언된 변수는 Block Scope를 갖게 되고 외부에서 참조되지 않는다.
#2. 변수 호이스팅 방식
자바스크립트의 Parser는 코드를 실행하기 전에 해당 코드를 한번 훑어보는 '코드 평가 과정'을 거치는데, 이 때 '변수 선언문'을 미리 실행해두기 때문에 뒤에서 선언된 변수도 앞의 코드에서 참조할 수 있게 된다. 이를 변수 호이스팅이라고 한다.
var의 호이스팅 방식과 let과 const의 호이스팅 방식에는 차이가 있다.
console.log(v3); // undefined
var v3 = "v3";
console.log(v3); // v3
var로 선언한 변수의 경우, 변수가 선언되기 전에 참조를 하더라도 에러를 발생시키지 않는다.
왜냐하면 코드 실행전에 자바스크립트 엔진이 미리 변수를 선언하고, undefined로 초기화해 두었기 때문이다.
let과 const의 호이스팅은 다른 방식으로 동작한다.
console.log(l3); // ReferenceError: Cannot access 'a' before initialization
let l3 = "l3";
console.log(l3); // l3
변수 l3를 변수가 선언되기 전에 참조하려고 하니 에러가 발생한다.
let 또는 const로 변수를 선언하는 경우, 코드 실행 전에 자바스크립트 엔진이 변수 선언만 해두고, 초기화는 코드 실행 과정에서 변수 선언문을 만났을 때 수행한다. 그렇기 때문에 호이스팅이 발생하기는 하지만, 값을 참조할 수 없어서 호이스팅이 발생하지 않는 것처럼 보이는 것이다.
변수의 선언과 초기화 사이에 일시적으로 변수 값을 참조할 수 없는 구간인 TDZ(Temporal Dead Zone)에 빠졌기 때문에 보이는 현상이다.
#3. 전역객체 프로퍼티 여부
| var로 선언된 변수는 전역객체(브라우저 환경의 경우 window)의 프로퍼티다.
var a = 10;
console.log(window.a); // 10
console.log(a); // 10
브라우저 환경에서 위 코드를 실행하면 var로 선언한 변수 a는 전역객체인 window의 프로퍼티로 할당된다.
| let, const로 선언된 변수는 전역객체 프로퍼티가 아니다.
let a = 10;
console.log(window.a); // undefined
console.log(a); // 10
브라우저 환경에서 위 코드를 실행하면 let이나 const로 선언한 변수 a는 브라우저 전역객체인 window의 프로퍼티로 할당되지 않았다.
#4. 재선언
| var는 중복 선언이 '가능'하다.
// 1. 변수의 선언과 동시에 초기화
var a = 10;
console.log(a); // 10
// 2. 변수의 선언과 동시에 초기화
var a = 20;
console.log(a); // 20
// 3. 변수의 선언 (초기화X)
var a;
console.log(a); // 20
var 키워드를 사용하여 선언한 변수는 같은 변수명으로 재선언이 가능하다.
a라는 변수명에 값을 할당하고, 다시 a라는 변수명에 초기화없이 선언을 한 경우에는 마지막에 할당된 값이 변수에 저장된다.
단, 초기화 없이 선언만 한 경우에는 에러는 발생하지 않지만 선언문 자체가 무시된다.
기존에 선언해둔 변수의 존재를 잊어버리고, 같은 변수명으로 값을 재할당하는 등의 실수가 발생하기 쉽다.
| let과 const는 재선언이 '불가능'하다.
// let 중복 선언
let a = 10;
let a = 20; // SyntaxError: Identifier 'a' has already been declared
// const 중복 선언
const b = 10;
const b = 20; // SyntaxError: Identifier 'b' has already been declared
반면에 let과 const 키워드를 사용하여 선언한 변수는 재선언이 불가능하다.
위의 예시 코드에서 처럼 이미 선언한 변수를 다시 선언할 경우, 이미 선언된 적이 있다는 에러를 발생시킨다.
var 키워드에 비해서 선언에 대해 엄격하기 때문에 코드의 안정성을 높여줄 수 있는 방식이다.
#5. 재할당
| var와 let은 값의 재할당이 '가능'하다.
var a = 10;
a = 20;
console.log(a); // 20
let b = 10;
b = 20;
console.log(b); // 20
var와 let은 '변수'를 선언하는 키워드이기 때문에 변수 선언 및 초기화 이후에 반복해서 다른 값을 재할당 할 수 있다.
| const는 값의 재할당이 '불가능'하다.
const c = 10;
c = 20; // TypeError: Assignment to constant variable.
const는 '상수(변하지 않는 값)'를 선언하는 키워드이다.
선언 및 초기화를 하면 다른 값을 재할당 할 수 없다.
const d; // SyntaxError: Missing initializer in const declaration
참고로 const는 처음 선언할 때 반드시 초기화(값 할당)을 해주어야한다.
정리
기본적으로 변수의 Scope는 최대한 좁게 만드는 것을 권장한다. 코드가 길어지면 내가 원하는 의도와 다른 값을 띄워줄 수 있는 var보다는 let과 const 키워드를 사용하고, 변하지 않는 값(상수)이라면 const 키워드를 사용하도록 하자. 그렇다면 좀 더 안전하고 견고한 코드를 짤 수 있다.
[참고자료]
코딩교육 티씨피스쿨
4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등
tcpschool.com
[자바스크립트] 변수 선언 방식 차이: var / let / const
자바스크립트의 변수 선언은 var로만 가능했으나, ES6(ES2015)부터 let과 const가 추가 되었다. 옛날의 var가 최신의 let(변수), const(상수)로 분리되었다고 생각할 수 있으나, 내부 사정은 상당히 다르다.
curryyou.tistory.com
'Front-End > JavaScript' 카테고리의 다른 글
[JavaScript] 콜백함수(Callback Function) (0) | 2023.09.08 |
---|---|
[JavaScript] Closure(클로저) (1) | 2023.09.05 |
[JavaScript] Execute Context(실행 컨텍스트) (0) | 2023.08.31 |