JavaScript - Scope

vlwkaos·2021년 8월 26일
0

JavaScript

목록 보기
1/1

JavaScript - Scope

Declaration

  • Scope: 선언한 것을 찾을 수 있는 범위. 정적인 속성이다.
  • Activation: 선언한 것을 언제 실제로 사용할 수 있는지. 동적인 속성이다.
    - Scope 내에서 바로 접근 가능한 것들이 있고, 실행 후 선언부(실제 선언하는 코드)까지 도달해야 접근 가능한 것들이 있다.
ScopeActivationDuplicatesGlobal prop.
constBlockdecl.(TDZ)XX
letBlockdecl.(TDZ)XX
functionBlock*startOO
classBlockdecl.(TDZ)XX
importModulesame as exportXX
varFunctionstart, partiallyOO
  • decl. (TDZ): 선언된 범위(Scope) 내에서 실행될 때 접근 가능하다.
  • Duplicates: 중복 선언이 가능한가에 대한 여부
  • Global prop.: 전역 객체에 추가되는지에 대한 여부
  • 함수의 Scope는 일반적으로 Block 범위, strict mode가 아닐 때는 Function 범위

아래에서 더 자세하게 살펴보자

Temporal Dead Zone(TDZ)

  • let, const에 해당한다.
{
  console.log(x); // ???
  const x;
}

선언된 범위(Scope) 내에서 선언까지 도달하기 전 사용이 불가능하기 떄문에 에러를 뱉는다.

범위 내에서 선언에 도달하기 까지의 구간을 TDZ(일시적 사용 불가 구간)라고 한다.

  • TDZ에서 변수는 초기화되어있지 않다.
  • 초기화되어있지 않은 변수 접근을 시도하면 ReferenceError가 발생한다.
  • 선언하는 부분에 도달하면 변수는 대입한 값으로 초기화 되거나 undefined가 된다.

다음 예제는 TDZ가 실제로 일시적으로 존재함을 알려준다.

if (true) { // myVar이 선언되어있는 스코프에 진입
  const func = () => {
    console.log(myVar); // 함수 실행시점에 myVar이 TDZ를 벗어났으면 실행
  };

  // 아래 myVar 선언되기 전에 사용하려는 경우 ReferenceError가 뜰 것이다.
  
  let myVar = 3; // TDZ가 끝났다.
  func(); // myVar의 TDZ가 끝났기 때문에 에러가 아니다.
}

Function declaration

함수가 있는 Scope에 접근할 때 함수 선언은 Scope내 어디에 있든 항상 실행된다.
즉, Scope내 어디서든 선언만 되어있다면 언제든 사용할 수 있다.

단, const, let을 이용하여 함수를 선언/할당한 경우는 예외이다.

단점은, 함수를 실행한 뒤에 선언한 변수가 함수 선언 내부에 쓰이는 특이 케이스가 있다는 것이다.

funcDecl(); // funcDecl이 선언된 Scope니까 일반적으로 가능.

const MY_STR = 'abc'; 
function funcDecl() {
  assert.throws(
    () => MY_STR, // 하지만 이 const가 나중에 선언된 것이므로 위는 MY_STR의 TDZ임
    ReferenceError);
}

Class declaration

Class는 선언한 이후에 사용 가능해야한다. 왜냐하면 class의 상속 기능인 extends가 expression이기 때문이다. extends시에는 계산이 이뤄지기 때문에 다음과 같은 코드가 가능하다.

const identity = x => x;
class Cat extends identity(Animal) {}

이런 expression에 대한 statement는 그 시점에 하는게 맞다.

ℹ️ expression은 값을 나타내고, statement는 행위의 선언이다.

var과 hoisting

👀 JavaScript - Hoisting

아까 표에서 var는 Javascript실행시 부분적으로 사용가능하다고 되어있었다.

var x = 123;

var의 선언은 두 부분으로 나뉜다.

  • 선언부 var x: var로 선언된 변수를 담고있는 가장 안쪽의 함수 Scope ⚠️ Block scope가 아님
  • 대입부 x = 123: 값은 대입한 시점 이후부터 사용가능
function f() {
  
  assert.equal(x, undefined); // 가장 안쪽의 함수 Scope에서 선언. undefined로 초기화됨
  if (true) {
    var x = 123; // 이제 123 값을 갖게됨 + Block안에서 선언했지만 위 설명대로..
    
    assert.equal(x, 123);
  }
  
  assert.equal(x, 123); // 여기선 123
}

참조

profile
Web, Tech Ethics

0개의 댓글