관련지식
javascript, var, const, let, array, hoisting
이번엔 변수를 선언할때 사용하는 키워드 몇개를 설명하려고 합니다. 전통적으로 많이 사용해온 var
키워드와 나중에 추가된 const
, let
키워드가 있는데 어떻게 다를까요?
아래와 같은 소스가 있다고 가정하겠습니다.
function define() {
var a = 10;
const b = 20;
let c = 30;
console.log('second', a, b, c);
}
define();
const
먼저 아래 const
로 선언한 변수를 재정의 해보겠습니다.
function define() {
var a = 10;
const b = 20;
let c = 30;
console.log('second', a, b, c);
//추가
try {
b = 30;
}
catch(e) {
console.log(e);
}
}
define();
try...catch
로 묶은것에서 짐작되겠지만, 이 코드는 ‘TypeError: Assignment to constant variable.’ 오류가 납니다. const
로 선언된 변수는 한번 정의된 값을 다시 재정의 하는것이 불가능합니다. 따라서 다른 변수와 다르게 값을 정의하지 않는 변수 선언이 불가능합니다.
const KEY1 = 'name'; //정상
const KEY2; //Missing initializer in const declaration 오류
var
var
키워드를 이해할때 반드시 필요한 개념이 호이스팅(Hoisting) 이죠. 이전에 ‘[javascript] scope와 호이스팅(hoisting)’ 에서 다루었던 것처럼 var
키워드로 선언한 변수는 호이스팅이 발생합니다. 아래 코드를 추가해보겠습니다.
function define() {
console.log('first', a); //추가
var a = 10;
만약 자바 코드였다면 위 소스는 오류가 나겠지만 자바스크립트 에서는 undefined
가 출력됩니다. 그리고 변수 b와 c를 사용할 경우엔 오류가 납니다. const
와 let
키워드로 선언한 변수는 호이스팅이 발생하지 않기 때문입니다.
참고
console.log('first', a); //first undefined 출력
console.log(c); //ReferenceError: c is not defined
undefined
와ReferenceError: c is not defined
은 의미가 비슷해보이지만 실제로는 큰 차이가 있습니다. undefined 는 참조할 대상은 있지만 정의된 값이 없는 상태, ReferenceError는 참조할 변수 자체가 없는 것입니다.
let
호이스팅이 없으면 무엇이 달라질까요?
var a = 10;
const b = 20;
let c = 30;
...
var a = 50; //추가
let c = 60; //추가
같은 함수 안에서 밑에쪽에 동일한 이름을 재선언하는 코드를 추가하였습니다. 실행하면 어떻게 될까요? ‘var a = 50;’ 은 별다른 이상이 없지만 ‘let c = 60;’ 에서는 오류가 납니다. var
키워드는 호이스팅으로 인해 변수 선언부가 스코프의 최상위 한곳으로 정리되지만, let
은 그렇지 않죠. 따라서 중복 선언으로 오류가 발생합니다.
다음 소스를 보겠습니다.
for(var i = 0; i < 3; i++) {
}
for(let j = 0; j < 3; j++) {
}
console.log(i); //3 출력
console.log(j); //ReferenceError
var
로 선언한 변수 i는 호이스팅으로 인해 함수 스코프만 적용됩니다. 하지만 let
으로 선언한 변수는 호이스팅이 없기 때문에 지역 스코프가 적용됩니다. 자바에서 int
로 선언했을때와 똑같은 효과가 나타났네요!
Lexical Scope
이번엔 아래와 같이 소스를 추가해보겠습니다.
var d = 'a'; //추가
const e = 'b'; //추가
let f = 'c'; //추가
function define() {
console.log('first', a);
...
d = 'd'; //추가
e = 'e'; //추가
f = 'f'; //추가
}
define()
함수 안에서 d, e, f 변수의 값을 할당하려고 하지만 동일한 함수 스코프 내에 선언된 변수가 없습니다. 따라서 상위 Lexical Scope 에서 변수를 찾게 되는데, 변수 e는 const
로 선언되어 있네요. 따라서 “e = ‘e’;” 코드는 오류가 발생합니다. 이번엔 소스 위치를 조금 바꿔보겠습니다.
function define() {
...
d = 'd';
f = 'f';
}
define();
var d = 'a'; //이동
let f = 'c'; //이동
변수에 ‘d’, ‘f’ 값을 할당하려고 할때 상위 스코프의 변수를 찾는것은 동일합니다. 그런데 변수의 선언 위치가 define() 실행 이후로 옮겨졌네요. 이 소스는 아래와 같이 동작합니다.
var d; //호이스팅
function define() {
...
d = 'd';
f = 'f'; //ReferenceError
}
define();
d = 'a'; //이동
let f = 'c'; //이동
변수 d는 사용하는데 문제 없지만 변수 f는 호이스팅이 발생하지 않기 때문에 define()
함수 안에서는 참조 할수가 없습니다.
정리
cosnt
키워드는 그 특징이 뚜렸하지만 var
, let
은 비슷하면서 다른 부분이 많아서 처음 접할때 헷갈릴수 있습니다. 특징을 정확히 알아두셔야 코딩을 하면서 자잘한 실수를 줄일수 있을것 같네요.
'javascript' 카테고리의 다른 글
브라우저 알림(Notification) 팝업에 버튼 추가 with ServiceWorker (0) | 2019.11.25 |
---|---|
브라우저 알림(Notification) 팝업에 폰트 크기 적용하기 (0) | 2019.11.22 |
[javascript] viewer.js 를 이용하여 이미지 뷰어 만들기(feat. Masonry Layout) (1) | 2019.11.05 |
[javascript] 핀터레스트처럼 Masonry Layout 적용해보기 (1) | 2019.11.04 |
[javascript] require.js 에서 DataTables 로딩시 경로를 잘못 찾을때 (0) | 2019.10.29 |