변수 선언 방식을 배웠는데 let을 사용하더라.
추가학습에서는 const를 추가적으로 배워보고 let과 어떤 차이점이 있는지 블로그에 정리해보라고 하더라.
그런데 var에 대한 언급이 따로 있지 않아 기왕 적는김에 var, let, const가 무엇이고 어떠한 차이점이 있는지도 같이 적으려 한다.
var같은 경우 자바스크립트에서 예전부터 es5까지 사용하던 변수 선언 키워드다. 식별자 앞에 var를 적어 사용해주면 된다.
var hong = 'seongkwon"
var같은 경우 es6에 나온 const와 let에 의해 완전히 대체되었는데 그 이유는 사용함에 있어 여러가지 문제점을 갖고 있었기 때문이다.
ㄱ. 변수의 중복 선언 허용
var hong = "seongkwon";
var hong = "erase";
const와 let과는 다르게 var는 중복 선언을 허용한다. 근데 문제는 이 것이 초기화를 같이 하느냐 안 하느냐에 따라서 달라지는 것.
var x = "hong;
var x = "seongkwon"
console.log(x)
//seongkwon
var y = ="hong";
var y;
console.log(y)
// hong
위 코드와 같이 x는 hong에서 seongkwon으로 기존 값이 대체되었는데, y의 경우는 초기화가 되지 않을 경우 '무시'된다. 짧은 코드는 변수를 헷갈릴 일이 적겠지만 코드가 길어질 경우 선언했던 변수를 다시 선언하게 되면 먼저 선언된 변수 값이 대체된다거나의 문제가 발생할 수도 있다는 것.
ㄴ. 함수 레벨 스코프
대부분의 프로그래밍 언어는 블록 레벨 스코프를 가지고 있다. 자바 개발자 등 다른 개발자들이 자바스크립트 들어와서 헷갈렸다고 하는 것이 바로 이것인데 자바스크립트에서는 var키워드로 변수를 선언했을 시 '함수 레벨 스코프를 가지고 있기 때문에 코드 블록 내에서 변수를 선언해도 함수 스코프 밖이면 전역변수 취급을 한다. if문이나 for문의 경우도 전역변수 취급을 한는 것!
var x = 1;
var y = 1;
if(true) {
var x = 10;
}
test = function () {
var y = 1;
}
console.log(x)
// 10
console.log(y)
// 1
var 키워드의 사용은 전역변수 사용을 높일 확률이 커 중복 선언 확률을 높힐 수 있다는 문제가 발생한다!
ㄷ. 변수 호이스팅
var 키워드는 호이스팅에 의해 선언문이 코드 위쪽으로 올라간다. let과 const의 경우 발생하긴 하나 하지 않는 것처럼 동작해 이 부분에서 차이를 가지고 있다.
console.log(x);
// undefined;
var x = "hong";
원래 호이스팅이 없더라면 이 코드는 에러가 발생할 게 분명하다. x를 선언하고 초기화하기도 전에 값을 조회하니깐 말이다. 하지만 호이스팅에 의해 위 코드는 아래처럼 동작한다.
var x;
console.log(x);
x = "hong"
그래서 값을 선언하고 할당하기 전에 변수를 조회해도 에러가 나지 않는 것! 다만 값 선언만 위로 이동하는 것처럼 작동하기 때문에 undefined 값이 찍힌다.
변수 선언문 전에 참조하는 것은 위와같이 에러를 따로 일으키지는 않지만 위에서 아래로 내려오는 코드 특성상 다른 사람이 이해하기 어려울 수 있고 가독성을 떨어뜨릴 수 있다. 또한 undefined로 값이 찍히기 대문에 오류 발생시킬 여지가 있다는 것!
es6 이후 등장한 변수 선언 키워드다. 기존 var에서 느껴지던 불편함을 해소, 문제점을 해결하기 위해 등장했다.
ㄱ. 변수 중복 선언 금지
var의 경우 중복 선언을 허용했지만 let의 경우 중복 선언일 경우 SyntaxError을 발생시킨다.
ㄴ. 블록 레벨 스코프
전역변수 남발 위험을 높이던 함수 레벨 스코프에서 블록 레벨 스코프로!
ㄷ. 변수 호이스팅 작동 안 하는 것처럼
var의 경우 변수 선언 이전에도 변수를 참조할 수 있었는데 let의 경우는 다르게 동작한다.
let x = "hong"
console.log(x)
이 경우에 x는 정의되지 않았다고 ReferenceError을 발생시는데 이를 보면 호이스팅이 일어나지 않는 것처럼 보인다.
사실 var키워드의 경우는 선언단계와 초기화단계가 한 번에 일어난다. (선언하면 undefined로 초기화되는 것, 그래서 호이스팅 발생하고 값 조회하면 undefined로 찍히는 것!) 하지만 let의 경우는 선언단계와 초기화단계가 따로 일어나고 선언은 런타임 이전 자바스크립트 엔진에 의해 먼저 실행되지만 선언문에 도착했을 때 초기화가 진행되는 것이다.
그 과정에서 초기화 전에 변수를 참조하게 되면 TDZ라고 하는 일시적 사각지대에 도달하면서 referenceerror를 찍는 것!
이는 호이스팅이 일어나지 않는 것처럼 보이지만 사실 호이스팅은 작동한다.
let x = "hong"
{
console.log(x);
let x = "seongkwon"
}
위 코드를 실행시키면 referenceError을 발생시킨다. 호이스팅이 일어나지 않는다면 전역변수인 hong을 찍을텐데 말이다. 이는 let키워드가 호이스팅이 일어난다는 반증으로 생각할 수 있다.
참고로 자바스크립트에서 모든 선언문은 호이스팅이 발생한다고 한다. 다만 class, let, const만이 일어나지 않는 것처럼 작동할 뿐이다.
const는 constant의 줄임말이라더라. let과 마찬가지로 es6에서 등장한 변수 선언 키워드. 다만 let과 다른 부분이 존재한다. 느낌상 let보다 엄격하고 빡빡한 느낌쓰.
const는 일반적으로 var과 비교해 보았을 때 let과 같은 특징들을 가지고 있다. 블록레벨스코프, 중복선언 금지, 호이스팅 관련 등
ㄱ. 선언과 동시에 초기화 의무
const x = "hong"
const y ="seongkwon"
// 안됨.
ㄴ. 재할당 금지
var의 경우는 중복선언, 재할당을 허용, let은 재할당만을 허용했다면 const의 경우는 아예 이를 금지한다.
ㄷ. 객체의 값 변경 허용
const에 원시값을 할당했을 경우에는 값을 변경할 수 없지만(재할당 금지), 객체를 할당했다고 하면 값을 변경할 수 있다.(객체 자체를 바꾸는 것이 아닌 객체의 값을 변경한다는 것)
변수 선언에는 일반적으로 const를 사용하고 바뀔 수 있는 값(재할당이 필요한 경우에) let을 한정적으로 사용하는 것이 일반적이라고 하긴 하드라.
공부를 하다보면 아직까지도 var키워드를 사용하는 예제들을 많이 볼 수 있다. 더 이상 var를 사용하지는 않지만 구글링을 하거나 기존 예제들을 풀어볼때 var을 많이 볼 수 있으므로 어떠한 역할을 수행하고 이러저러한 특징을 가지고 있구나 정도만 알고있는 것도 나쁘지 않을 것 같다.
또 let과 const의 경우는 정확히 어떠한 차이점을 가지고 있고 어떠한 상황에서 사용하는지도 알고있어야 할 듯 싶다.