Language/Javascript

[Javascript/ES6] 모던자바스크립트 변수 var, let, const 차이

재은초 2023. 8. 4. 18:13
반응형

var

  • ES5까지 변수를 선언할 수 있는 유일한 방법은 var 키워드를 사용하는 것이었다.
  • 하지만 아래와 같은 var 키워드의 특징 때문에 문제가 발생했고 ES6는 이러한 var 키워드의 단점을 보완하기 위해 let과 const 키워드를 도입하였다.

var 키워드 생략 허용

  • 암묵적 전역 변수를 양산할 가능성이 크다.

함수 레벨 스코프(Function-level scope)

  • 함수의 코드 블록만을 스코프로 인정한다. 함수 범위란 말 그대로 함수를 기준으로 범위를 구분한다는 뜻으로 함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다. 이는 전역 변수를 남발할 가능성을 높인다.
  • 하지만 함수를 제외한 for, if, while 등과 같은 문법 안에서 선언한 변수는 그 문법 밖에서도 계속 유효했었기 때문에 때로는 변수가 자칫 전역변수의 역할을 할 수 있다.
{
  var x = 3;
}

function myFunction() {
  var y = 4;
}

console.log(x);
console.log(y);

>>> 3
>>> Uncaught ReferenceError: y is not defined

변수 중복 선언 허용

  • 똑같은 이름으로 변수를 한 번 더 선언하게 되면, 에러가 발생하는 것이 아니라 그냥 기존의 변수를 덮어써 버린다. 중복 코드로 인한 오류 발생 가능성이 있어서 사용하지 않는 것이 좋다.
var myVariable;                // 선언
myVariable = 'codeit'          // 값 할당
console.log(myVariable);

var myVariable = 'Codeit!';;     // 선언과 동시에 값 할당
console.log(myVariable);

>>> codeit
>>> Codeit!

변수 호이스팅(hoisting)

  • var 변수는 선언되기 이전에도 변수에 접근할 수 있다. var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어지기 때문이다.
  • 즉, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화(초기화 단계)한다. 따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않지만 다만 undefined를 반환한다. 이후 변수 할당문에 도달하면 비로소 값이 할당된다. 이러한 현상을 변수 호이스팅(Variable Hoisting)이라 한다.
console.log(myVariable);    // undefined
var myVariable = 'codeit'
console.log(myVariable);    // codeit

 

let

블록 레벨 스코프

  • 대부분의 프로그래밍 언어는 블록 레벨 스코프(Block-level scope)를 따르지만 자바스크립트는 함수 레벨 스코프(Function-level scope)를 따른다.
  • 블록 레벨 스코프(Block-level scope)로 모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.
let foo = 123; // 전역 변수

{
  let foo = 456; // 지역 변수
  let bar = 456; // 지역 변수
}

console.log(foo); // 123
console.log(bar); // ReferenceError: bar is not defined

변수 중복 선언 금지

  • var 키워드로는 동일한 이름을 갖는 변수를 중복해서 선언할 수 있었다. 하지만, let 키워드로는 동일한 이름을 갖는 변수를 중복해서 선언할 수 없다. 변수를 중복 선언하면 문법 에러(SyntaxError)가 발생한다.
var foo = 123;
var foo = 456;  // 중복 선언 허용

let bar = 123;
let bar = 456;  // Uncaught SyntaxError: Identifier 'bar' has already been declared

호이스팅

  • 자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다.
  • 호이스팅(Hoisting)이란 var 선언문이나 function 선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성을 말한다.
  • 하지만 var 키워드로 선언된 변수와는 달리 let 키워드로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.
console.log(foo); // undefined
var foo;

console.log(bar); // Error: Uncaught ReferenceError: bar is not defined
let bar;

전역 객체와 let

  • 전역 객체(Global Object)는 모든 객체의 유일한 최상위 객체를 의미하며 일반적으로 Browser-side에서는 window 객체, Server-side(Node.js)에서는 global 객체를 의미한다.
  • var 키워드로 선언된 변수를 전역 변수로 사용하면 전역 객체의 프로퍼티가 된다. 하지만 let 키워드로 선언된 변수를 전역 변수로 사용하는 경우, let 전역 변수는 전역 객체의 프로퍼티가 아니다. let 전역 변수는 보이지 않는 개념적인 블록 내에 존재하게 된다.
var foo = 123; // 전역변수
console.log(window.foo); // 123

let bar = 123; // 전역변수
console.log(window.bar); // undefined

 

const

선언과 초기화

  • const는 변하지 않는 값(상수)을 위해 사용되며, let은 재할당이 자유로우나 const는 재할당이 금지된다.
  • 주의할 점은 const는 반드시 선언과 동시에 할당이 이루어져야 한다는 것이다. 그렇지 않으면 다음처럼 문법 에러(SyntaxError)가 발생한다.
const FOO; // SyntaxError: Missing initializer in const declaration

const FOO = 123;
FOO = 456; // TypeError: Assignment to constant variable.

블록 레벨 스코프

{
  const FOO = 10;
  console.log(FOO); //10
}
console.log(FOO); // ReferenceError: FOO is not defined

객체의 경우

  • const는 재할당이 금지된다. 이는 const 변수의 타입이 객체인 경우, 객체에 대한 참조를 변경하지 못한다는 것을 의미한다. 하지만 이때 객체의 프로퍼티는 보호되지 않는다. 다시 말하자면 재할당은 불가능하지만 할당된 객체의 내용(프로퍼티의 추가, 삭제, 프로퍼티 값의 변경)은 변경할 수 있다.
  • 객체의 내용이 변경되더라도 객체 타입 변수에 할당된 주소값은 변경되지 않는다. 따라서 객체 타입 변수 선언에는 const를 사용하는 것이 좋다. 만약에 명시적으로 객체 타입 변수의 주소값을 변경(재할당)하여야 한다면 let을 사용한다.
const user = { name: 'Lee' };

// const 변수는 재할당이 금지된다.
// user = {}; // TypeError: Assignment to constant variable.

// 객체의 내용은 변경할 수 있다.
user.name = 'Kim';

console.log(user); // { name: 'Kim' }

 

Reference

반응형