상세 컨텐츠

본문 제목

자바스크립트 / var / let / const 차이

언어/Javascript + Typescript

by moonionn 2020. 7. 3. 01:39

본문

var, let, const

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
  • 변수 선언 방식인 var, let, const를 사용한 b, c, d의 경우 함수 밖에서 불러올 수 없습니다.
  • 하지만 변수 선언을 하지 않은 a는 글로벌 객체의 성격을 가진 걸 확인할 수 있습니다.

 

this.a
//result: 1

this.b
//result: undefined

this.c
//result: undefined

this.d
//result: undefined

마찬가지로 this 객체에서 각 변수를 호출하면

b, c, d는 존재하지 않는 것으로 나타납니다.

 

 

이로써

 

선언된 변수들은 변수가 선언된 실행 콘텍스트(execution context) 안에서 만들어집니다.

선언되지 않은 변수들은 항상 전역변수입니다.

 

라는 말을 증명해보였습니다.

 


var

중복선언 가능

var prince = 'Harry';
console.log(prince);
// -> 'Harry'

var prince = 'William';
console.log(prince);
// -> 'William'
  • let, const가 존재하지 않았던 ES6 이전에 독단적으로 존재하던 변수 선언 방식입니다.
  • var를 이용해 같은 이름의 변수를 두 번 선언해도 오류가 나지 않고 내용이 변경됩니다.
  • 이런 var의 경우 아래와 같은 문제점을 가집니다.

 

호이스팅

변수 선언이 함수 또는 전역 코드의 상단에 이동하는 것과 같은 행동을 "호이스팅(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가 이미 선언된 것으로 드러남

 

function-scoped

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, const

let: 중복 선언 불가, 하지만 할당값 변경은 가능

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: 중복 선언 불가, 할당값 변경 불가

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 << block-scoped

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로 선언을 해주어도 오류가 나지 않습니다.

(물론 그렇다고 같은 변수 이름을 마구마구 쓰면...)

 

let, const << 호이스팅 x

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://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone_and_errors_with_let

 

let - JavaScript | MDN

let 구문은 블록 유효 범위를 갖는 지역 변수를 선언하며, 선언과 동시에 임의의 값으로 초기화할 수도 있다. The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the int

developer.mozilla.org

https://www.zerocho.com/category/ECMAScript/post/5757d74345041aaae7493479

 

(ECMAScript) ES2015(ES6) Const, Let

안녕하세요. 이번 시간부터 본격적으로 ES2015(ES6)에서 어떻게 자바스크립트가 바뀌었는지 알아보겠습니다! 먼저 변수를 선언할 때 var 외에도 const(constant, 상수)와 let이 생겼습니다. const, let 기존

www.zerocho.com

 

관련글 더보기

댓글 영역