본문 바로가기
개발/Javascript

[Javascript] let, const와 블록 레벨 스코프

by devhooney 2022. 7. 6.
728x90

모던 자바스크립트 Deep Dive 정리

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

- 함수의 코드 블록만을 스코프로 인정

- for 문의 변수 선언문에서 선언한 변수를 for 문의 코드 블록 외부에서 참조 가능

2. var 키워드 생략 허용

- 암묵적 전역 변수를 남발할 가능성

3. 변수 중복 선언 허용

- 의도하지 않은 변수값의 변경이 일어날 가능성

4. 변수 호이스팅

- 변수를 선언하기 이전에 참조 가능

 

이러한 단점을 보완하기 위해 var 대신 let, const 사용

 

1. let

1.1 블록 레벨 스코프

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

함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.

 

- 블록 레벨 스코프(Block-level scope)

모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.

let ex = 123; // 전역 변수

{
  let ex = 456; // 지역 변수
  let ex2 = 456; // 지역 변수
}

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

- let 키워드로 선언된 변수는 블록 레벨 스코프를 따름

- 위 예제에서 코드 블록 내에 선언된 변수 ex는 블록 레벨 스코프를 갖는 지역 변수이다. 전역에서 선언된 변수 ex와는 다른 별개의 변수이다. 또한 변수 ex2도 블록 레벨 스코프를 갖는 지역 변수이다. 따라서 전역에서는 변수 ex2를 참조할 수 없다.

 

1.2 변수 중복 선언 금지

- var 키워드로는 동일한 이름을 갖는 변수를 중복해서 선언있음.

- let 키워드로는 동일한 이름을 갖는 변수를 중복해서 선언할 수 없다. 변수를 중복 선언하면 문법 에러(SyntaxError)가 발생한다.

 

1.3 호이스팅

- JS는 모든 선언(var, let, const, function, class)을 호이스팅한다. 호이스팅(Hoisting)이란, var 선언문이나 function 선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성을 말한다.

- 변수의 생성 3단계

1. 선언 단계(Declaration phase)

변수를 실행 컨텍스트의 변수 객체(Variable Object)에 등록한다. 이 변수 객체는 스코프가 참조하는 대상이 된다.

2. 초기화 단계(Initialization phase)

변수 객체(Variable Object)에 등록된 변수를 위한 공간을 메모리에 확보한다. 이 단계에서 변수는 undefined로 초기화된다.

3. 할당 단계(Assignment phase)

undefined로 초기화된 변수에 실제 값을 할당한다.

 

- var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다.

// 스코프의 선두에서 선언 단계와 초기화 단계가 실행된다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 있다.
console.log(ex); // undefined

var ex;
console.log(ex); // undefined

ex = 1; // 할당문에서 할당 단계가 실행된다.
console.log(ex); // 1

https://poiemaweb.com/es6-block-scope - var 키워드로 선언된 변수의 생명 주기

- let 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다. 

// 스코프의 선두에서 선언 단계가 실행된다.
// 아직 변수가 초기화(메모리 공간 확보와 undefined로 초기화)되지 않았다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 없다.
console.log(ex); // ReferenceError: foo is not defined

let ex; // 변수 선언문에서 초기화 단계가 실행된다.
console.log(ex); // undefined

ex = 1; // 할당문에서 할당 단계가 실행된다.
console.log(ex); // 1

https://poiemaweb.com/es6-block-scope - let 키워드로 선언된 변수의 생명 주기

 

1.5 전역 객체와 let

- 전역 객체(Global Object)는 모든 객체의 유일한 최상위 객체를 의미

- Browser-side에서는 window 객체, Server-side(Node.js)에서는 global 객체를 의미

- var 키워드로 선언된 변수를 전역 변수로 사용하면 전역 객체의 프로퍼티가 된다.

var ex = 123; // 전역변수

console.log(window.ex); // 123

let ex2 = 123; // 전역변수

console.log(window.ex2); // undefined

 

2. const

- const는 상수(변하지 않는 값)를 위해 사용.

 

2.1 선언과 초기화

- const는 재할당 불가

- 선언과 동시에 할당이 이루어져야 함

 

2.2 상수

// 10의 의미를 알기 어렵기 때문에 가독성이 좋지 않다.
if (rows > 10) {
}

// 값의 의미를 명확히 기술하여 가독성이 향상되었다.
const MAXROWS = 10;
if (rows > MAXROWS) {
}

 

2.3 const와 객체

- const 변수의 타입이 객체인 경우, 객체에 대한 참조를 변경하지 못한다는 것을 의미

- 재할당은 불가능하지만 할당된 객체의 내용(프로퍼티의 추가, 삭제, 프로퍼티 값의 변경)은 변경은 가능

const user = { name: 'Lee' };

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

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

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

 

3. var vs. let vs. const

- ES6를 사용한다면 var 키워드는 사용하지 않는다.

- 재할당이 필요한 경우에 한정해 let 키워드를 사용한다. 이때 변수의 스코프는 최대한 좁게 만든다.

- 변경이 발생하지 않는(재할당이 필요 없는 상수) 원시 값과 객체에는 const 키워드를 사용한다. const 키워드는 재할당을 금지하므로 var, let 보다 안전하다.

 

728x90