Skip to content

Latest commit

 

History

History
214 lines (151 loc) · 7.91 KB

15_let, const 키워드와 블록 레벨 스코프.md

File metadata and controls

214 lines (151 loc) · 7.91 KB

15. let, const 키워드와 블록 레벨 스코프

📌 15.1 var 키워드로 선언한 변수의 문제점

ES5까지는 var 키워드로만 변수를 선언할 수 있었다.
var 키워드로 선언한 변수는 다음과 같은 특징을 갖는다.

변수 중복 선언 허용

var 키워드로 선언한 변수는 중복 선언이 가능하며, 에러를 발생시키지 않는다.
초기화문이 있는 변수 선언문 은 자바스크립트 엔진에 의해 var 키워드가 없는 것처럼 동작한다.
초기화문이 없는 변수 선언문 은 무시된다.

  • 동일한 이름의 변수가 이미 선언되어 있는 것을 모르고 변수를 중복 선언 및 할당하면 의도치 않게 먼저 선언된 변수 값이 변경되는 부작용 이 발생한다.
var x = 1;
var y = 1;
var x = 100; // 에러 없이 재할당된다.
var y; // 에러 없이 무시된다.

함수 레벨 스코프

var 키워드로 선언한 변수는 함수 레벨 스코프만을 인정한다.
if문, for문 등을 포함한 코드 블록 내에서 선언해도 해당 지역 변수로 인정되지 않는다.

  • 함수 레벨 스코프는 전역 변수를 남발할 가능성을 높이며, 의도치 않게 전역 변수가 중복 선언 될 수 있다.
var i = 10;

for (var i = 0; i < 5; i++) {
  console.log(i); // 0 1 2 3 4
}

console.log(i); // 5

변수 호이스팅

var 키워드로 변수를 선언하면 변수 호이스팅에 의해 변수 선언문이 스코프의 선두로 끌어올려진 것처럼 동작한다.
따라서 변수 선언문 이전에 참조할 수 있고, undefined를 반환한다.

  • 이는 에러를 발생시키지는 않지만 프로그램의 흐름상 맞지 않아 가독성을 떨어뜨리고 오류를 발생시킬 여지 를 남긴다.
console.log(foo); // undefined
var foo;

📌 15.2 let 키워드

ES6에서 새로운 변수 선언 키워드 letconst가 도입되었다. var키워드와 let키워드의 주요 차이점은 다음과 같다.

변수 중복 선언 금지

let 키워드는 이름이 같은 변수를 중복 선언하면 문법 에러(SyntaxError)가 발생한다.

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

블록 레벨 스코프

let 키워드로 선언한 변수는 모든 코드 블록(함수, if문, for문, while문, try/catch문 등)을 지역 스코프로 인정하는 블록 레벨 스코프(block-level-scope)를 따른다.

{
  let foo = 1;
}
console.log(foo); // ReferenceError: foo is not defined
let i = 10; // 전역 스코프
function foo() { // 함수 레벨 스코프
  let i = 100;
  for (let i = 1; i < 3; i++) { // 블록 레벨 스코프
    console.log(i); // out: 1 2
  }
  console.log(i); // out: 100
}
foo();
console.log(i); // out: 10

변수 호이스팅

  • var 키워드로 선언한 변수는 런타임 이전에 선언 단계초기화 단계가 한번에 진행되었다.
  • let 키워드로 선언한 변수는 런타임 이전에 선언 단계만 실행되고, 런타임에 변수 선언문에 도달했을 때 초기화 단계가 실행된다.

var-lifecycle let-lifecycle


  • 초기화 단계가 실행되기 이전에 변수에 접근하려고 하면 참조 에러(ReferenceError)가 발생한다.

  • let 키워드로 선언한 변수를 참조할 수 없는 사이 구간을 일시적 사각지대(Temporal Dead Zone, TDZ)라고 한다.

    console.log(foo) // ReferenceError: foo is not defined
    let foo;
    
  • 변수 선언문(초기화) 이전에는 참조할 수 없어 호이스팅이 일어나지 않는 것처럼 보일 수 있다. 하지만 호이스팅은 명확히 발생한다.
    아래 예시에서 호이스팅이 발생하지 않는다면 전역변수 foo의 값을 출력해야하지만, 호이스팅으로 블록 스코프 foo의 선언 단계가 완료 되었기 때문에 참조 에러(ReferenceError)가 발생했다.

    let foo = 1;
    {
      console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
      let foo = 2;
    }

전역 객체와 let

var 키워드로 선언한 전역 변수와 전역 함수, 그리고 선언하지 않은 변수에 값을 할당한 암묵적 전역은 전역객체 window의 프로퍼티가 된다.

var x = 1; // 전역 변수
y = 2; // 암묵적 전역
function foo() {} // 전역 함수

console.log(window.x); // 1
console.log(window.y); // 2
console.log(window.foo); // foo() {}

let 키워드로 선언한 변수는 전역 객체의 프로퍼티가 아니다. let 전역변수는 보이지 않는 개념적인 블록 내에 존재한다.

let x = 1;
console.log(window.x); // undefined

// 객체에 존재하지 않는 프로퍼티에 접근하면 undefined를 반환하며, ReferenceError가 발생하지 않는다.

📌 15.2 const 키워드

const 키워드의 특징은 let 키워드와 대부분 동일하지만 다음과 같은 차이점을 갖는다.

선언과 초기화

const 키워드로 선언한 변수 역시 블록 레벨 스코프를 가지며, 변수 호이스팅이 발생하지 않는 것처럼 동작한다.
단, const 키워드로 선언한 변수는 반드시 선언과 동시에 초기화해야한다.

const foo = 1;
const bar; // SyntaxError: Missing initializer in const declaration

재할당 금지

const 키워드로 선언한 변수는 재할당이 금지된다.

const foo = 1;
foo = 2; // TypeError: Assignment to constant variable.

상수

const 키워드는 상수를 표현하기에 적합한 특징을 갖고 있다.

  • const 키워드로 선언된 변수에 원시 값을 할당한 경우, 원시 값은 변경할 수 없는 값(immutable value)이고 const 키워드에 의해 재할당이 금지되므로 할당된 값을 변경할 수 있는 방법은 없다.

  • 상수는 상태 유지와 가독성, 유지보수의 편의를 위해 적극적으로 사용해야한다.

  • 일반적으로 상수는 대문자로 선언하고, 여러 단어로 이뤄진 경우에는 언더스코어 _ 로 구분해서 스네이크 케이스로 표현한다.

    const TAX_RATE = 0.1;
    let preTaxPrice = 100;
    let afterTaxPrice = preTaxPrice + (preTaxPrice * TAX_RATE);

const 키워드와 객체

const 키워드로 선언된 변수에 객체를 할당한 경우 값을 변경할 수 있다.

  • 객체는 변수 값의 재할당 없이도 직접 변경이 가능하기 때문이다.
  • 객체가 변경되더라도 변수에 할당된 참조 값은 변경되지 않는다.
const person = {
  name: 'Lee',
};
person.name = 'Kim';
console.log(person); // {name: 'Kim'}

따라서 const키워드는 재할당을 금지할 뿐 '불변'을 의미하지 않는다 는 것에 유의해야한다.


📌 15.3 var vs. let vs. const

varlet, const 키워드는 다음과 같이 사용하는 것을 권장한다.

  • ES6를 사용한다면 var 키워드는 사용하지 않는다.
  • 재할당이 필요한 경우에 한정해 let 키워드를 사용한다. 이때 변수의 스코프는 최대한 좁게 만든다.
  • 변경이 발생하지 않고 읽기 전용으로 사용하는 상수 원시 값과 객체에는 const 키워드를 사용한다.

변수를 선언하는 시점에는 대부분 재할당 필요 여부를 알기 어려우므로 일단 const 키워드를 사용하자.