변수 선언문의 차이점
세 가지 종류의 변수 선언문
자바스크립트에서 변수를 처음 정의(또는 설정)하는 것을 "변수를 선언한다"라고 합니다.
변수를 선언하려면 자바스크립트의 규칙에 따라 선언해야 합니다. 자바스크립트에서는 변수를 선언할 때 '변수 선언문(Statement)'으로 합니다.
변수 선언문은 하나만 있는 것이 아니라, 세 가지 종류의 선언문이 있습니다. 아래는 이 세 가지 선언문입니다.
자바스크립트는 이 세 가지 변수 선언문을 제공하여, 개발자가 변수 선언 시 코드의 편리성, 안정성, 충돌 방지, 그리고 예기치 않은 동작을 방지할 수 있도록 선택할 수 있게 합니다.
각각의 변수 선언문의 특징과 차이점을 이해하는 것은 자바스크립트 개발에서 매우 중요합니다.
초기화(Initialization)
자바스크립트에서 변수가 선언될 때 값을 할당하는 과정을 "초기화"라고 합니다.
반면, const는 선언과 동시에 반드시 초기화를 해야 하며, 값을 할당하지 않으면 에러가 발생합니다.
예제
var
var a = 10;
console.log(a); // 출력: 10
var b;
console.log(b); // 출력: undefined
let
let a = 10;
console.log(a); // 출력: 10
let b;
console.log(b); // 출력: undefined
const
const 선언 - 반드시 초기화해야 함
const age = 30;
const 선언 - 초깃값을 할당하지 않으면 에러
const age; // Uncaught SyntaxError: Missing initializer in const declaration
스코프(Scope)
스코프(Scope)란 '범위' 또는 '영역'을 의미하며 여기에서는 변수나 함수에 접근할 수 있는 유효한 코드의 영역을 의미합니다.
| 비교 항목 | var |
let |
const |
|---|---|---|---|
| 스코프 | 글로벌(전역) 스코프 또는 함수 스코프를 가짐 | 글로벌(전역) 스코프 또는 블록({}) 스코프를 가짐 |
글로벌(전역) 스코프 또는 블록({}) 스코프를 가짐 |
var
var로 선언된 변수는 글로벌 스코프 또는 함수 스코프를 가집니다.
var로 선언한 변수는 함수 밖에서 선언되었으면 글로벌에서 사용 가능(유효)하고, 함수 내에서 선언되었으면 해당 함수 내에서만 사용 가능(유효)합니다.
let, const
블록({})의 의미
자바스크립트에서 블록은 중괄호 {}로 둘러싸인 코드 영역을 의미합니다.
다음은 블록의 일반적인 형태들입니다.
if () { // if 블록
// ...
} else { // else 블록
// ...
}
function exampleFn() { // 함수 블록
// ...
}
{ // 임의의 독립적인 블록 (일반적으로 잘 사용되지는 않음)
let temp = 10; // temp는 이 블록 내에서만 유효
}
for () { // for 블록
// ...
}
예제
var
/* 글로벌(전역) 스코프 */
var globalVar = "글로벌 변수"; // 코드 전체 영역에서 유효한 변수임
function exampleFunction() {
/* 함수 스코프 */
var functionVar = "함수 내 변수"; // 함수 내 전체 영역에서 유효한 변수임
if (true) {
var blockVar = "블록 내 변수"; // if 문의 블록({}) 내에서 선언되었지만, 함수 내 전체 영역에서 유효함
console.log(functionVar); // 출력: "함수 내 변수"
console.log(blockVar); // 출력: "블록 내 변수"
}
// if 문의 블록({}) 내에서 선언되었지만, 함수 내 전체 영역에서 유효한지 확인
console.log(blockVar); // 출력: "블록 내 변수"
}
exampleFunction();
console.log(globalVar); // 출력: "글로벌변수"
console.log(functionVar); // ReferenceError 발생(함수 외부에서 유효하지 않음, functionVar is not defined)
let
/* 글로벌(전역) 스코프 */
let globalVar = "글로벌 변수"; // 이 파일(또는 스크립트)의 최상위 블록 전체에서 유효함
function exampleFunction() {
/* 함수 블록 스코프 */
let functionVar = "함수 블록 변수"; // 함수 전체 블록에서 유효함
if (true) {
let innerBlockVar = "if 블록 변수";
console.log(functionVar); // 출력: "함수 블록 변수"
console.log(innerBlockVar); // 출력: "if 블록 변수"
}
// if 블록 스코프 외부이므로 참조 불가
// console.log(innerBlockVar); // ReferenceError (innerBlockVar is not defined)
}
if (true) {
let ifBlockVar = "if 블록 변수";
console.log(ifBlockVar); // 출력: "if 블록 변수"
}
exampleFunction();
console.log(globalVar); // 출력: "글로벌 변수"
// console.log(functionVar); // ReferenceError (functionVar is not defined)
// console.log(ifBlockVar); // ReferenceError (ifBlockVar is not defined)
const
/* 글로벌(전역) 스코프 */
const globalVar = "글로벌 변수"; // 이 파일(또는 스크립트)의 최상위 블록 전체에서 유효함
function exampleFunction() {
/* 함수 블록 스코프 */
const functionVar = "함수 블록 변수"; // 함수 전체 블록에서 유효함
if (true) {
const innerBlockVar = "if 블록 변수";
console.log(functionVar); // 출력: "함수 블록 변수"
console.log(innerBlockVar); // 출력: "if 블록 변수"
}
// if 블록 스코프 외부이므로 참조 불가
// console.log(innerBlockVar); // ReferenceError (innerBlockVar is not defined)
}
if (true) {
const ifBlockVar = "if 블록 변수";
console.log(ifBlockVar); // 출력: "if 블록 변수"
}
exampleFunction();
console.log(globalVar); // 출력: "글로벌 변수"
// console.log(functionVar); // ReferenceError (functionVar is not defined)
// console.log(ifBlockVar); // ReferenceError (ifBlockVar is not defined)
재선언(Redeclaration) 및 재할당(Reassignment)
'재선언'이란 같은 스코프 내에서 동일한 식별자(변수 이름)로 변수를 다시 선언하는것을 말합니다.
'재할당'이란 같은 스코프 내에서 동일한 식별자(변수 이름)로 할당 연산자(=)를 사용하여 변수의 값을 바꾸는 것을 말합니다.
| 비교 항목 | var |
let |
const |
|---|---|---|---|
| 재선언 | 가능 | 불가능 | 불가능 |
| 재할당 | 가능 | 가능 | 불가능 |
예제
var
var로 선언된 변수는 같은 스코프 내에서 재선언(Redeclaration) 및 재할당(Reassignment)이 가능합니다.
이미 var로 선언된 변수의 값을 언제든지 새로운 값으로 변경할 수 있으며, 동일한 식별자(변수 이름)로 변수를 다시 선언해도 오류가 발생하지 않으며, 마지막에 할당된 값으로 덮어쓰게 됩니다.
/* 초기 선언 및 값을 할당 */
var myValue = 10;
console.log(myValue); // 출력: 10
/* 재할당 */
myValue = 20;
console.log(myValue); // 출력: 20 (값이 변경됨)
/* 재선언 (var를 다시 사용) */
var myValue = "Hello";
console.log(myValue); // 출력: "Hello" (오류 없이 다시 선언되고 값이 덮어쓰기 됨)
let
let으로 선언된 변수는 같은 스코프 내에서 재선언(Redeclaration)이 불가합니다.
같은 스코프 내에서 이미 let으로 선언된 변수를 동일한 식별자(변수 이름)로 변수를 다시 선언하면 오류가 발생합니다.
// 같은 스코프 내에서 let 동일한 식별자(변수 이름)로 변수를 다시 선언하면 오류가 발생
let exampleLet = 10;
let exampleLet = 100; // Uncaught SyntaxError: Identifier 'exampleLet' has already been declared
// 서로 다른 스코프 내에서 let 동일한 식별자(변수 이름)로 변수를 다시 선언은 가능
let exampleLet = 10;
console.log(exampleLet); // 출력: 10
if (true) {
let exampleLet = 100;
console.log(exampleLet); // 출력: 100
}
console.log(exampleLet); // 출력: 10
let으로 선언된 변수의 재할당은 변수를 선언한 스코프와 상관없이 접근 가능한 스코프 내에서 동일한 식별자로 변수의 값을 바꿀 수 있습니다.
// 글로벌 스코프
let globalVar = "글로벌 변수";
console.log(globalVar); // "글로벌 변수"
// 재할당 가능
globalVar = "재할당된 글로벌 변수";
console.log(globalVar); // "재할당된 글로벌 변수"
if (true) {
// 블록 스코프
let blockVar = "블록 변수";
console.log(blockVar); // "블록 변수"
// 재할당 가능
blockVar = "재할당된 블록 변수";
console.log(blockVar); // "재할당된 블록 변수"
}
// 블록 밖에서는 참조 불가
// console.log(blockVar); // ReferenceError
const
const로 선언된 변수는 같은 스코프 내에서 재선언(Redeclaration)이 불가합니다.
같은 스코프 내에서 이미 const로 선언된 변수를 동일한 식별자(변수 이름)로 변수를 다시 선언하면 오류가 발생합니다.
// 같은 스코프 내에서 const 동일한 식별자(변수 이름)로 변수를 다시 선언하면 오류가 발생
const exampleConst = 10;
const exampleConst = 100; // Uncaught SyntaxError: Identifier 'exampleConst' has already been declared
// 서로 다른 스코프 내에서 const 동일한 식별자(변수 이름)로 변수를 다시 선언은 가능
const exampleConst = 10;
console.log(exampleConst); // 출력: 10
if (true) {
const exampleConst = 100;
console.log(exampleConst); // 출력: 100
}
console.log(exampleConst); // 출력: 10
const로 선언된 변수의 재할당은 변수를 선언한 스코프와 상관없이 접근 가능한 스코프 내에서 동일한 식별자로 할당 연산자(=)를 사용한 변수의 값을 변경할 수 없습니다.
=)를 사용한 재할당 불가
const exampleConst = 10;
/* 동일한 식별자로 할당 연산자(=)를 사용한 변수의 값을 변경할 수 없습니다. */
exampleConst = 100; // Uncaught TypeError: Assignment to constant variable.
하지만, 변수의 값이 객체나 배열처럼 참조를 저장하는 데이터의 경우에는 속성이나 값을 추가, 업데이트 또는 제거할 수 있습니다.
다음은 const로 할당된 일반 객체(Plain object)의 속성·값 추가, 업데이트, 제거에 대한 예제입니다.
// 일반 객체 선언
const person = {
name: 'Alice',
age: 30
};
// 1. 속성 추가
person.city = 'Seoul'; // 새로운 속성 추가
console.log(person); // 출력: { name: 'Alice', age: 30, city: 'Seoul' }
// 2. 속성 업데이트
person.age = 31; // 기존 속성 값 업데이트
console.log(person); // 출력: { name: 'Alice', age: 31, city: 'Seoul' }
// 3. 속성 제거
delete person.city; // 속성 제거
console.log(person); // 출력: { name: 'Alice', age: 31 }
// 배열 선언
const numbers = [1, 2, 3];
// 1. 요소 추가
numbers.push(4); // 배열 끝에 요소 추가
console.log(numbers); // 출력: [1, 2, 3, 4]
// 2. 요소 업데이트
numbers[0] = 10; // 첫 번째 요소 값 업데이트
console.log(numbers); // 출력: [10, 2, 3, 4]
// 3. 요소 제거
numbers.pop(); // 배열 끝에서 요소 제거
console.log(numbers); // 출력: [10, 2, 3]
호이스팅(Hoisting)
호이스팅이란 자바스크립트에서 변수 및 함수 선언이 스코프의 상단으로 "끌어올려지는" 동작을 말합니다. 즉, 코드의 실행 단계에서 변수나 함수 선언이 실제로 작성된 위치와 상관없이 스코프의 최상단으로 끌어올려지는 현상입니다.
| 비교 항목 | var |
let |
const |
|---|---|---|---|
| 호이스팅 | 발생(단, 변수가 선언된 위치보다 먼저 참조되면 undefined가 할당 됨) |
발생(단, 변수가 선언된 위치보다 먼저 참조되면 에러 발생) | 발생(단, 변수가 선언된 위치보다 먼저 참조되면 에러 발생) |
예제
var
/*
* 아래의 var myName으로 선언된 myName 변수가
* 스코프의 최 상단에 위치한 것처럼 호이스팅 됨
* 다만 선언된 변수만 올라가고,
* 선언 시 할당한 값은 원래 자리에 남게 됨.
*
* 선언 시 할당한 값이 없기 때문에
* 실제 변수가 선언된 위치보다 먼저 참조되면
* undefined로 초기화됩니다.
*/
/* 실제 변수가 선언된 위치보다 먼저 참조 */
console.log(myName); // 출력: undefined (선언만 호이스팅, 값은 undfined로 할당)
/* var로 선언한 변수의 위치 */
var myName = "John";
let, const
TDZ(Temporal Dead Zone, 일시적 사각지대)
// TDZ 영역 시작
// ↓
console.log(myVar); // ReferenceError: Cannot access 'myVar' before initialization
// ↑
// TDZ 영역 종료
let myVar = 10;
// TDZ 영역 시작
// ↓
console.log(myVar); // ReferenceError: Cannot access 'myVar' before initialization
// ↑
// TDZ 영역 종료
const myVar = 10;
자바스크립트 변수 선언 방법과 스코프의 중요성
- 올바른 변수 선언 방법과 스코프의 이해는 코드의 정확성과 안정성을 보장하는 데 중요합니다.
- 변수의 범위를 명확히 지정하고, 변수의 충돌을 방지하여 예기치 않은 동작을 방지할 수 있습니다.
- 스코프를 제어함으로써 변수의 가시성과 생명주기를 관리할 수 있습니다.
- 변수 선언 방법과 스코프의 올바른 사용은 코드의 가독성, 유지 보수성, 재사용성을 향상시킵니다.
- 효율적인 변수 관리는 개발자의 생산성을 향상시키고 디버깅을 용이하게 만들어줍니다.
따라서, 변수 선언 방법과 스코프에 대한 이해는 자바스크립트 개발에서 필수적이며, 올바르게 활용함으로써 안정적이고 효율적인 코드를 작성할 수 있습니다.
효율적인 자바스크립를 사용하려면 var 변수 선언 방식은 사용하지 마세요!
명세서
| 명세서 사양 | |
|---|---|
| Variable Statement |
ECMAScript® 2027 Language Specification #sec-variable-statement |
호환성
| 문 |
데스크탑 Chrome
|
데스크탑 Edge
|
데스크탑 Firefox
|
Safari
|
Node.js
|
|---|---|---|---|---|---|
var
|
1 | 12 | 1 | 1 | 0.10 |
let
|
49 | 14 | 44 | 10 | 6 |
const
|
21 | 12 | 36 | 5.1 | 6 |