Posts [JavaScript] 자바스크립트 Scope
Post
Cancel

[JavaScript] 자바스크립트 Scope

JavaScript의 핵심 개념 중 하나인 Scope에 대해 알아보자!

스코프 (Scope)

스코프 : 스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙

1
2
3
4
5
6
7
8
9
var x = "global";

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

foo(); //  function scope
console.log(x); //  global

이름 같은 x가 중복 선언되었다. 전역에 선언된 x는 어디에서든 참조할 수 있다. 그러나 foo 함수 내부에서 선언된 변수 x는 foo 내부에서만 참조할 수 있고 함수 외부에서는 참조할 수 없다. 이러한 규칙을 스코프라고 한다.

스코프의 구분

자바스크립트에서는 스코프를 구분하면 다음과 같이 2가지로 구분할 수 있다.

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

모든 변수는 스코프를 갖고, 변수의 관점에서 스코프를 구분하면 다음과 같이 2가지로 구분할 수 있다.

전역 변수 (Global Variable) 전역에서 선언된 변수이며 코드 어디에서든지 참조할 수 있다 지역 변수 (Local Variable) 지역(함수) 내에서 선언된 변수이며 그 지역과 그 지역의 하부 지역에서만 참조할 수있다.

자바스크립트 스코프의 특징

자바스크립트는 기본적으로 함수 레벨 스코프를 따른다. 함수 레벨 스코프란 함수 코드 블록 내에 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다는 것이다.

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

전역 스코프 (Global Scope)

전역에 변수를 선언하면 이 변수는 어디서나 참조할 수 있는 전역 스코프를 갖는 변수가 된다. var 키워드로 선언한 전역변수는 window의 프로퍼티이다.

1
2
3
4
5
6
7
8
9
10
var global = 'global';
function foo {
    var local = 'local';
    console.log(global); // global
    console.log(local); // local
}
foo();

console.log(global); // global
console.log(local); // Uncaugh ReferenceError: local is not defined

변수 global은 전역에서 선언되었고 local은 foo 함수 내부에서 선언되었다. 따라서 전역 스코프에서 함수 내부에 선언된 local에 접근하려고 하면 에러가 발생한다.

전역변수의 사용은 변수의 이름이 중복될 수 있고, 프로젝트가 커질 경우 함수에 의해 전역변수의 값이 변경될 경우 전역변수에 저장되어 있는 값을 파악하기 쉽지 않기 때문에 지양해야 한다.

함수 레벨 스코프 (Function-Level Scope)

함수 코드 내에서 선언되는 변수는 함수 코드 블록 내에서만 참조가 가능하다

1
2
3
4
5
6
7
var a = 10;
function foo() {
  var b = 20;
}
foo();
console.log(a); // 10;
console.log(b); // Uncaught ReferenceError: b is not defined

자바스크립트는 함수레벨 스코프를 사용한다. 즉, 함수 내에서 선언된 매개변수와 변수는 함수 외부에서 유효하지 않다. 따라서 b를 출력할 때 에러가 발생한다.

함수 내에 존재하는 함수인 내부 함수의 경우를 살펴보자!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var x = "global";

function foo() {
  var x = "local";
  console.log(x); // local

  function bar() {
    // 내부함수
    console.log(x); //  local
  }

  bar();
}
foo();
console.log(x); // global

내부함수는 자신을 포함하고 있는 외부함수의 변수에 접근할 수 있다. 이는 매우 유용하다. 클로저와 같이 내부 함수가 더 오래 생존하는 경우, 타 언어와는 다른 움직임을 보인다.

함수 bar에서 참조하는 변수 x는 함수 foo에서 선언된 지역변수이다. 이는 실행컨텍스트의 스코프 체인에 의해 참조 순위에서 전역 변수 x가 뒤로 밀렸기 때문이다.

실행 컨텍스트와 클로저에 대해서는 이후 포스팅할 예정이다.

블록 레벨 스코프 (Block-Level Scope)

모든 코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서 참조할 수 없다.

1
2
3
4
5
6
7
8
9
let foo = "foo";
if (true) {
  let bar = "bar";
  console.log(foo); //  foo
  console.log(bar); //  bar
}

console.log(foo); //  foo
console.log(bar); //  Uncaught ReferenceError: bar is not defined.

자바스크립트 ES6의 let 키워드는 블록 레벨 스코프를 따르기 때문에 if 문 내부의 블록에서 선언된 bar 변수는 외부에서 접근할 수 없기 때문에 에러가 발생한다.

렉시컬 스코프

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

1
2
3
4
5
6
7
8
9
10
var x = 1;
function foo() {
  var x = 10;
  bar();
}
function bar() {
  console.log(x);
}
foo(); //  1
bar(); //  1

예제의 함수 bar은 전역에서 선언되었다. 따라서 bar의 상위 스코프는 전역 스코프이고 전역 변수 x의 값 1을 두번 출력한다.

Reference

This post is licensed under CC BY 4.0 by the author.

[JavaScript] var, let, const 차이

[ToyProject] 카카오톡 클론 프로젝트(1)

Comments powered by Disqus.