SCOPE

스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙이다. 식별자는 자신이 어디에서 선언됐는지에 의해 자신이 유효한 범위를 갖는다.

var x = 'global';

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

이름이 같은 변수 x가 중복 선언되어있는 예시이다. 전역으로 선언된 x는 어디에서든 참조할 수 있지만 foo 함수 내부에서 선언된 x는 내부에서만 참조할 수 있고, 함수 외부에서는 참조할 수 없다. 이러한 규칙을 스코프라고 한다. 모든 변수는 스코프를 가진다.

  • 전역 스코프 ( Global Scope ) : 코드 어디에서든지 참조 가능

  • 지역 스코프 ( Local Scope or Function-Level Scope) : 함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조 가능

타 언어는 블록 레벨 스코프 ( block-level scope )를 따른다. 하지만 자바스크립트는 함수 레벨 스코프( function-level scope ) 를 따른다. 함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록내에서만 유효하며, 함수 외부에서는 유효하지 않다.

단, ECMAScript 6에서 도입된 let 키워드를 사용하면 블록 레벨 스코프를 사용할 수 있다.

var x = 0;
{
  var x = 1;
  console.log(x); // 1
}
console.log(x);   // 1

let y = 0;
{
  let y = 1;
  console.log(y); // 1
}
console.log(y);   // 0

전역 변수는 전역 객체(Global Object)인 window 의 프로퍼티이다.

var x = 'global';

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

전역 변수의 사용은 변수 이름이 중복될 수 있으며, 의도치 않은 재할당에 의한 상태 변화로 코드를 예측하기 어렵게 만드므로 사용을 억제해야한다.

Lexical Scope

lexical scope는 함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정된다. 자바스크립트는 lexical scope를 따르므로 함수를 선언한 시점에 상위 스코프가 결정된다.

var x = 1;

function foo() {
  var x = 10;
  bar();
}

function bar() {
  console.log(x);
}

foo(); // 1
bar(); // 1

lexical scope를 따르므로, foo(), bar() 호출시 1이 출력되는 것을 확인할 수 있다.

최소한의 전역변수 사용

자바스크립트는 변수명의 중복을 허용하므로, 전역변수의 무분별한 사용은 무척 위험하다. 전역 변수를 반드시 사용해야할 이유가 없다면, 지역변수를 사용하고, 변수의 범위인 스코프는 좁을수록 좋다.

var MYAPP = {};
MYAPP.student = {
  name: 'Faker',
  gender: 'male'
};

전역변수를 최소화하는 방법 중 하나는 전역변수 객체를 하나 생성해서 사용하는 것이다.

즉시 실행 함수

즉시 실행 함수(IIFE, Immediately-Invoked Function Expression)를 사용하면, 전역변수 사용을 억제할 수 있다.

(function () {
  var MYAPP = {};

   MYAPP.student = {
    name: 'Faker',
    gender: 'male'
  };

  console.log(MYAPP.student.name); // Faker
}());

console.log(MYAPP.student.name);
VM1857:12 Uncaught ReferenceError: MYAPP is not defined
    at <anonymous>:12:13

이 방법을 사용하면 전역변수를 만들지 않으므로 라이브러리 등에서 자주 사용되며, 즉시 실행 함수는 즉시 실행되고 그 후 바로 사라진다.

참조 페이지

Last updated