var, let, const는 자바스크립트의 변수 선언 키워드입니다.
그렇다면 이들 사이에는 어떤 차이점이 존재하고,
어느때에 어느 방식으로 변수를 선언해야 할까요?
선언된 변수들은 변수가 선언된 실행 콘텍스트(execution context) 안에서 만들어집니다.(출처링크)
선언되지 않은 변수들은 항상 전역변수입니다.
이것이 무슨 말일까요?
예시를 만들어봅시다.
function A(){
a = 1;
var b = 1;
let c = 1;
const d = 1;
};
A();
console.log(a);
//result: 1
console.log(b);
console.log(c);
console.log(d);
//result: Uncaught ReferenceError: b is not defined
//result: Uncaught ReferenceError: c is not defined
//result: Uncaught ReferenceError: d is not defined
this.a
//result: 1
this.b
//result: undefined
this.c
//result: undefined
this.d
//result: undefined
마찬가지로 this 객체에서 각 변수를 호출하면
b, c, d는 존재하지 않는 것으로 나타납니다.
이로써
선언된 변수들은 변수가 선언된 실행 콘텍스트(execution context) 안에서 만들어집니다.
선언되지 않은 변수들은 항상 전역변수입니다.
라는 말을 증명해보였습니다.
var prince = 'Harry';
console.log(prince);
// -> 'Harry'
var prince = 'William';
console.log(prince);
// -> 'William'
변수 선언이 함수 또는 전역 코드의 상단에 이동하는 것과 같은 행동을 "호이스팅(hoisting)"이라고 합니다.
다르게 말하자면 var 선언문의 경우 코드 안에서 가장 우선순위로 처리된다는 뜻입니다.
hositing = 'Hi~';
var hoisting;
console.log(hoisting);
//상위 코드는 아래와 같다.
var hoisting;
hoisting = 'Hi~';
console.log(hoisting);
//result: 'Hi~'
2번째 줄의 var hoisting이 최상단에 있는 것으로 취급되기 때문에 오류가 나지 않습니다.
아래 추가 예시를 볼까요?
console.log(hoisting2);
var hoisting2 = 'Hi~';
//상위 코드는 아래와 같다.
var hoisting2;
console.log(hoisting2);
hoisting2 = 'Hi~';
//result: undefined
// ReferenceError: hoisting2 is not defined이 나올 줄 알았지만
// hoisting2가 이미 선언된 것으로 드러남
var의 또다른 특징은 바로 function-scoped 적인 성격을 지녔다는 것입니다.
즉, 전역함수 외부에서 선언된 변수는 무조건 전역변수로 작동한다는 뜻입니다.
스코프의 영역이 넓을 수록 문제를 야기할 가능성이 커지기 때문에 이는 var가 지닌 큰 단점입니다.
무슨 뜻인지 예시를 보면서 이해해보도록 합니다.
var scopeProblem = 1;
function A(){
var scopeProblem = 2;
console.log(scopeProblem);
}
A();
// -> 2
console.log(scopeProblem);
// -> 1
전역변수로 선언된 scopeProblem의 값은 1,
함수A 내에서 선언된 scopeProblem의 값은 2가 되네요.
하지만 함수가 아닌 블럭 내부에서 선언된 함수는 전역변수 역할을 합니다.
var i = 'this will be nothing';
console.log(i);
// -> 'this will be nothing'
for (var i = 0; i < 3;) {
i++
}
console.log(i);
// -> 2
위 예시처럼 기존의 i의 값이 for문 안에서 선언된 i로 재할당됩니다.
let은 var와 다르게 재선언, 혹은 중복선언이 불가능합니다.
하지만 이미 선언된 변수의 값을 변경하는 것은 가능하기 때문에, 동적인 값을 필요로 하는 곳에 자주 쓰입니다.
let queen = 'Victoria';
let queen = 'Elizabeth';
console.log(queen);
//result: SyntaxError: Identifier 'queen' has already been declared
let queen = 'Victoria';
queen = 'Elizabeth';
console.log(queen);
//result: 'Elizabeth'
위 예시문은 이미 선언된 queen이라는 변수의 할당값을 변경해준 것 뿐이기 때문에 오류가 나지 않습니다.
이러한 let의 특징이 쓰이는 경우를 간단한 예시 두가지로 보도록 하겠습니다.
let year = 1995;
let myAge = 0;
while (year < 2020) {
year ++;
myAge ++;
};
console.log(`${year}년도, 나는 ${myAge}살`);
// -> 2020년도, 나는 25살
let clients = ['John', 'Abigail', 'Don'];
// 👇반복문을 돌 때 let을 사용!
for (let i = 0; i < clients.length; i++) {
console.log(`Welcome! ${clients[i]}`);
};
/*result :
Welcome! John
Welcome! Abigail
Welcome! Don */
const는 let처럼 중복선언도 불가능한데다, let과 다르게 값을 재할당 할 수도 없습니다.
constant = 상수
const king = 'Edward';
const king = 'George';
console.log(king);
//result: SyntaxError: Identifier 'king' has already been declared
const king = 'Edward';
king = 'George';
console.log(king);
//result: TypeError: Assignment to constant variable.
let과 const는 함수 스코프였던 var와 다르게 블록스코프를 따릅니다.
위에서 var의 스코프영역을 설명하며 들었던 예시를 let에 맞게 변형해 보았습니다.
let i = 'this will remain';
for (let i = 0; i < 3; i++) {
console.log(i);
//result: 0, 1, 2
}
console.log(i);
//result: 'this will remain'
const A = 'Good afternoon!';
function X(){
const A = 'Good evening!';
console.log(A);
};
if (true) {
const A = 'Good morning!';
console.log(A);
}
console.log(A);
X();
/*
result:
Good morning!
Good afternoon!
Good evening!
*/
전역변수 A,
그리고 지역변수로 작동하는 함수X안에서의 A,
if문 안에서의 A는 서로 다른 A이기 때문에 아무리 const로 선언을 해주어도 오류가 나지 않습니다.
(물론 그렇다고 같은 변수 이름을 마구마구 쓰면...)
var와 다르게 let과 const는 호이스팅(선언 끌어올리기)가 작동하지 않습니다.
myFav = 'Oasis';
let myFav;
console.log(myFav);
//result: ReferenceError: Cannot access 'myFav' before initialization
function X () {
console.log(A);
console.log(B);
var A = 1;
let B = 1;
}
X();
//result: undefined (A의 값)
//ReferenceError: Cannot access 'B' before initialization (B의 값)
참고
https://www.zerocho.com/category/ECMAScript/post/5757d74345041aaae7493479
console 객체 이용 / 자바스크립트 (0) | 2020.07.23 |
---|---|
async, await 사용 연습 / 자바스크립트 (0) | 2020.07.15 |
Promise 이해하기 2 (0) | 2020.07.14 |
Promise 이해하기 (0) | 2020.07.10 |
이벤트 루프(event loop), 호출스택과 태스크 큐 / 자바스크립트 (0) | 2020.07.07 |
댓글 영역