자바스크립트는 es6부터 기존의 var 에 let, const가 추가되었다.
옛날의 var가 최신의 let(변수), const(상수)로 분리되었다고 생각할 수 있으나, 내부 사정은 상당히 다르다.
(참고로 여전히 var도 함께 사용이 가능하다)
1. 중복선언 가능 여부
2. 재할당 가능 여부
3. 변수의 스코프 유효범위
4. 변수의 호이스팅 방식
5. 전역객체 프로퍼티 여부
// 첫번째 변수 선언+초기화
var a = 10;
console.log(a); // 10
// 두번째 변수 선언+초기화
var a = 20;
console.log(a); // 20
// 세번째 변수 선언(초기화X)
var a;
console.log(a); // 20
var로 선언한 변수는 중복해서 선언(+초기화)가 가능하다.
이 경우, 마지막에 할당된 값이 변수에 저장된다.
단, 초기화 없이 선언만 한 경우엔 선언문 자체가 무시된다.(에러는 발생하지 않음)
기존에 선언해둔 변수의 존재를 까먹고, 값을 재할당하게 되는 등의 실수가 발생하기 쉽다.
Java나 Python 같은 언어에 익숙한 경우, 이게 뭔가 싶을 수 있다.
// 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에 비해서 코드의 안정성을 높여줄 수 있는 방식으로, 다른 언어를 쓰던 사람들게도 익숙할 것이다.
var a = 10;
a = 20;
console.log(a); // 20
let b = 30;
b = 40;
console.log(b); // 40
var , let은 변수 선언 및 초기화 이후에 반복해서 다른값을 재할당 할 수 있다.
const c = 100;
c = 200 ; TypeError: Assignment to constant variable.
const는 상수를 선언하는 키워드이다.
처음에 선언 및 초기화한 뒤 다른값을 재할당 할 수 없다.
const는 처음 선언 할 때 반드시 초기화를 해주어야 한다.
스코프란?
유효한 참조 범위를 말한다.
예를들어 함수 내부에서 선언된 변수는 함수 내부에서만 참조가 가능하다.
이 경우 변수의 스코프틑 함수 내부로 한정된다.
!! 자바스크립트에서는 var로 선언된 변수의 스코프와 let,const로 선언한 변수의 스코프가 다르다. !!
var은 함수 내부에 선언된 변수만 지역변수로 한정하며, 나머지는 모두 전역변수로 간주한다.
function hello(){
var a = 10;
console.log(a);
}
hello(); // 10
console.log(a); //ReferenceError: a is not defined
위와 같이, hello() 함수 내부에서 선언된 a 라는 변수는 함수 내부에서만 참조가 가능하며, 외부에서 참조시 에러가 발생한다.
그런데 함수를 제외한 영역에서 var로 선언한 변수는 전역변수로 취급된다.
if(true){
var a = 10;
console.log(a); // 10
}
console.log(a); // 10
자바스크립트에서는 if,for,while 등의 코드 블럭 { ~코드블럭 안~ } 내부에서 var로 선언된 변수를 전역 변수로 간주한다.
그래서 블럭 외부에서도 어디에서나 참조 할 수 있다.
if(true){
let a = 10;
const b = 20;
console.log(a); // 10
console.log(b); // 20
}
console.log(a); // ReferenceError: a is not defined
console.log(b); // ReferenceError: a is not defined
function test() {
let c = 30;
console.log(c); // 30
}
console.log(c); // ReferenceError: a is not defined
let, const로 선언된 변수는 함수 내부는 물론, if,for 등의 코드블럭에서 선언된 변수도 지역변수로 취급한다.
정리해보면
- var : 함수 내부에 선언된 변수만 지역변수로 인정하는 함수 레벨 스코프
- let, const : 블록 내부에서 선언된 변수까지도 지역변수로 인정하는 블록 레벨 스코프
호이스팅 : 함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것
호이스팅에 대해서는 따로 글 추가할 예정
자바스크립트는 코드를 실행하기 전에 일종의 '코드 평과 과정'을 거치는데, 이 때
'변수 선언문'을 미리 실행두기 때문에 뒤에서 선언된 변수도 앞의 코드에서 참조할 수 있게 된다. 이를 변수 호이스팅이라고 한다.
var / let,const는 호이스팅 과정이 다르다.
console.log(a); // undefined
var a = 10;
console.log(a); // 10
변수 선언 전에 앞에서 변수가 참조되었는데도 에러가 발생하지 않는다.
이 이유는 코드 실행 전에 자바스크립트 엔진이
미리 변수를 선언하고 undefined로 초기화해 두었기 때문이다.
이것이 var로 선언된 변수의 호이스팅이다.