티스토리 뷰

JavaScript

스코프 (Scope)

da.som 2018. 12. 9. 00:06

원래는 JavaScript의 클로저(Closure) 에 대해 정리하려고 했는데, 클로저는 스코프(Scope) 개념과 밀접하기 때문에 먼저 스코프에 대해 정리해보려 한다.

스코프(Scope)

스코프는 프로그래밍 언어에서 유효범위를 말하는 것으로, 변수와 매개변수(parameter)의 접근성과 생존기간을 뜻한다.

JavaScript(ES6)의 지역 스코프는 함수 레벨블럭 레벨렉시컬 스코프 규칙을 따른다.
(참고로, JavaScript는 함수레벨만 지원해오다가 ES6(ECMAScript 6)부터 블럭 레벨 스코프를 지원한다고 한다.)

스코프의 종류로는 전역 스코프(Global Scope)지역 스코프(Local Scope) 가 있다.
변수가 함수 바깥이나 중괄호({}) 바깥에 선언되었다면 전역 스코프 에 정의된다고 한다. 전역 스코프에 정의된 변수는 코드 어느 곳에서든 해당 변수를 사용할 수 있다.
반면, 지역 스코프 에서 정의된 변수는 특정 부분에서만 사용이 가능하다.

함수 레벨 스코프(Functional Level Scope)

var 키워드로 선언된 변수나, 함수 선언식으로 만들어진 함수는 함수 레벨 스코프 를 갖는다.
즉, 함수 내부 전체에서 접근이 가능 하기 때문에 아래 코드는 아무런 문제없이 if문 안의 변수를 출력한다.

function scope () {
  if (true) {
    var foo = 'scope test';
  }
  console.log(foo); // scope test
}
scope();

블럭 레벨 스코프(Block Level Scope)

하지만, var foo 대신에 let 또는 const로 선언했을 경우는 에러가 나타나는 것을 볼 수 있다.
중괄호({}) 내부에서 ES6의 let, const 키워드를 사용해 변수를 선언하면, 그 변수는 중괄호 블럭 내부에서만 접근할 수 있는 블럭 레벨 스코프 변수가 되기 때문이다.

function scope () {
  if (true) {
    let foo = 'scope test';
    console.log(foo); // scope test
  }
  console.log(foo); // Uncaught ReferenceError: foo is not defined
}
scope();

위의 코드에서 let foo를 if문 블럭 내부에서 선언하였기 때문에, 해당 변수는 if문 내부에서만 사용할 수 있으며 if문 바깥에서 잘못된 참조를 하면 에러가 발생한다.

렉시컬 스코프(Lexical Scope)

JavaScript의 스코프는 함수를 호출할 때가 아니라, 선언 할 때 생긴다. 이것을 정적 스코프, 렉시컬 스코프 라고 부른다.

아래의 코드 결과를 예상해보자.

var foo = 'first';

function inner() {
  console.log(foo);
}

function wrapper() {
  var foo = 'second';
  inner();
}

wrapper();

언뜻 보면 'second'를 반환할 것 같지만 inner() 안의 foo는 wrapper() 안의 지역변수 var foo = 'second'가 아닌 전역변수 var foo = 'first'를 참조한다.

함수를 처음 선언하는 순간 함수 내부의 변수는 자기 스코프로부터 가장 가까운 곳에 있는 변수를 계속 참조하게 된다.
그래서 wrapper() 안에서 inner()를 호출해도, 이미 inner()가 선언 될 때 참조하고 있는 전역변수 foo의 값인 first를 반환하게 되는 것이다.

알고보니 매우 중요한 스코프

지금까지 설명한 내용은 스코프의 기본 뼈대 내용이며, 클로저를 설명하기 위해서는 스코프에 대한 이해가 전제되어야 하기때문에 원래는 여기까지만 간단히 정리하려했다.

그러나 앞서 설명한 내용을 바탕으로 중요한 개념들이 이어지기 때문에 실행 문맥(Execution Context), 스코프 체인(Scope Chain), 호이스팅(Hoisting) 에 대해 이어서 설명하도록 하겠다.

Reference

댓글