let, const, var (scope 차이점, Hoisting)

박선우·2023년 1월 10일
0

CS 스터디

목록 보기
8/53
post-thumbnail

🐶 Var, Let, Const 차이점 , Scope

1️⃣ Scope

  • 스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙이다. 자바스크립트는 이 규칙대로 식별자를 찾는다.
var x = 'global';

function foo () {
  var x = 'function scope';
  console.log(x);
}

foo(); // ?
console.log(x); // ?

2️⃣ Scope 구분

전역 스코프 (Global scope) : 코드 어디에서든지 참조할 수 있다
지역 스코프 (Local scope or Function-level scope) : 함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.

3️⃣ Var(전역 스코프)

  • var 키워드로 선언한 전역 변수는 전역 객체(Global Object) window의 프로퍼티이다.
var global = 'global';

function foo() {
  var local = 'local';
  console.log(global);
  console.log(local);
}
foo();

console.log(global);
console.log(local); //ReferenceError
  • 함수 레벨 스코프(Function-level scope)
    함수의 코드 블록만을 스코프로 인정한다. 따라서 전역 함수 외부에서 생성한 변수는 모두 전역 변수이다. 이는 전역 변수를 남발할 가능성을 높인다.
    for 문의 변수 선언문에서 선언한 변수를 for 문의 코드 블록 외부에서 참조할 수 있다.
  • var 키워드 생략 허용
    암묵적 전역 변수를 양산할 가능성이 크다.
  • 변수 중복 선언 허용
    의도하지 않은 변수값의 변경이 일어날 가능성이 크다.
  • 변수 호이스팅
    변수를 선언하기 이전에 참조할 수 있다.

4️⃣ Let(블록 레벨 스코프)

  • 블록 레벨 스코프(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

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

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

let bar = 123;
let bar = 456;  // Uncaught SyntaxError

5️⃣ Const(블록 레벨 스코프)

let과 거의 동일 하다.

  • 하지만, let은 재할당이 자유로우나 const는 재할당이 금지된다.
const FOO = 123;
FOO = 456; // TypeError:

⛔️ 주의 사항
const는 반드시 선언과 동시에 할당이 이루어져야 한다는 것이다. 그렇지 않으면 문법 에러(SyntaxError)가 발생한다

const FOO; // SyntaxError:

6️⃣ Hoisting

  • 변수나 함수를 선언했을 때 코드 범위(scope) 내의 최상단으로 끌어올려지는 것처럼 보이는 현상이다. 흔히 var 는 호이스팅이 발생하며, const 와 let 은 발생하지 않는다.

1단계: 선언 단계(Declaration phase)

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

2단계: 초기화 단계(Initialization phase)

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

3단계: 할당 단계(Assignment phase)
undefined로 초기화된 변수에 실제 값을 할당한다.

🫥 TDZ(Temporal Dead Zone, 일시적 사각지대)

  • var 키워드로 선언한 변수는 선언 단계와 초기화 단계가 한번에 이뤄진다. 즉, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화한다.
  • 따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined를 반환한다. 이후 변수 할당문에 도달하면 비로소 값이 할당된다.
  • let 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다.
  • 즉, 스코프에 변수를 등록(선언 단계)하지만 초기화 단계는 변수 선언문에 도달했을 때(코드 실행 후) 이뤄진다.
  • 초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생한다. 이는 아직 변수가 초기화되지 않았기 때문이다. 즉, 변수를 위한 메모리 공간이 아직 확보되지 않았기 때문이다.
  • 따라서 스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다. 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 ‘일시적 사각지대(Temporal Dead Zone; TDZ)’라고 부른다.

🫥 Hoisting 예제

☢️ 변수선언

// 호이스팅 때문에 선언이 끌어올려져서 오류 안남.
console.log(text); // (선언 + 초기화 된 상태)
text = 'Hanamon!'; // (선언 + 초기화 + 할당 된 상태)
var text;
console.log(text);
----------------------
// 호이스팅 때문에 선언이 끌어올려졌지만 초기화 안된 상태에서 참조해서 오류 남.
console.log(text); // (선언 된 상태, 초기화(메모리 공간 확보와 undefined로 초기화) 안되서 참조 불가능 -> 에러)
let text; // 여기서 초기화 단계가 실행됨
----------------------
const text; // 에러. 주의! 재할당 불가능! 선언과 동시에 할당해야함

☢️ 함수선언

a(); // 함수 선언문에서는 호이스팅 O
b(); // 함수 표현식이라서 호이스팅 X
function a() {
  console.log('Hello');
}
var b = function() {
  console.log('world');
}

출처 : https://poiemaweb.com/js-scope

profile
코린이 열심히 배우자!

0개의 댓글