티스토리 뷰

Javascript

Javascript Scope (유효범위)

Dev_YooJin 2018. 1. 19. 01:36


Scope(유효범위)는 자바스크립트를 포함한 모든 프로그래밍 언어의 기본적인 개념으로 확실한 이해가 필요하다. Scope란 변수에의 접근성과 생존기간(life-cycle)을 의미한다. 달리 말하자면 변수가 가지고 있는 참조 범위를 의미한다. 

Javascript의 Scope 종류는 다음과 같다.

  • 전역 Scope (Global scope) 코드 어디에서든지 참조할 수 있다. 
  • 지역 Scope (Local scope or Function-level scope) 정의된 함수 내에서만 참조할 수 있다. 

모든 변수는 Scope를 갖는다. 

  • 전역 변수 (Global variable) 전역 Scope를 갖는 변수. 
  • 지역 변수 (Local variable) 지역 Scope를 갖는 변수


JavaScript 유효범위의 특징

JavaScript 유효범위만의 특징을 크게 분류하여 나열하면 다음과 같습니다.

  • 함수 단위의 유효범위 (function-level scope)
  • 변수명 중복 허용
  • 암묵적 전역 (implied globals)
  • Lexical scoping (Static scoping)


Function-Level Scope

C-family language는 block-level scope를 사용한다. block-level scope란 code block({ … })내에서 유효한 scope를 의미한다.

하지만 자바스크립트는 function-level scope를 사용한다. function-level scope란 함수 코드 블럭 내에서 선언된 변수는 함수 코드 블럭 내에서만 유효하고 함수 외부에서는 유효하지 않다(참조할 수 없다)는 것이다.  

단, ECMAScript 6에서 도입된 let keyword를 사용하면 block-level scope를 사용할 수 있다.


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 scope를 갖는 전역 변수가 된다. 전역 변수는 전역 객체(Global Object) window의 프로퍼티이다.


var global = 'global';

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

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

변수 global는 함수 영역 밖의 글로벌 영역에서 선언되었다. 자바스크립트는 타 언어와는 달리 특별한 시작점이 없어서 위 코드와 같이 글로벌 영역에 변수나 함수를 선언하기 쉽다.

전역 변수의 사용은 변수명의 중복 등 여러 문제를 발생시키므로 가급적 사용을 억제하여야 한다.


// x.js
function foo () {
  // var i = 0;
  i = 0;
  // ...
}

// y.js
for(var i = 0; i < 5; i++) {
  foo();
  console.log(i);
}

2개의 파일로 분리된 자바스크립트 코드가 있다고 가정한다.


x.js와 y.js에 모두 변수 i와 존재한다. 이는 의도되지 않은 것이다. HTML에서 이 2개의 자바스크립트 파일을 로드하여 사용하면 변수 i는 중복된다.


<!DOCTYPE html>
<html>
<body>
  <script src='x.js'>
  <script src='y.js'>
</body>
</html>

x.js의 변수 i는 var 키워드를 사용하지 않았으므로 암묵적으로 전역 변수화 되고 y.js의 변수 i는 전역변수이다. 이때 자바스크립트는 변수명의 중복을 허용하므로 어떠한 에러 메시지도 발생시키지 않는다. 따라서 무한 반복 상태에 빠지게 된다. 

이와 같이 전역변수의 무분별한 사용은 무척 위험하다. 전역변수를 반드시 사용하여야 할 이유를 찾지 못한다면 지역변수를 사용하여야 한다. 변수의 범위인 스코프는 좁을수록 좋다. 

 코드가 길어지면 변수명의 중복이 발생하기 쉬워 예기치 못한 이상 동작의 원인이 되기 쉬우며, 전역변수는 지역변수보다 탐색에 걸리는 시간이 더 길다.


암묵적 전역 (implied globals)

아래의 foo 함수 내 변수 x에 1을 할당하였다. 하지만 foo 함수 내에는 변수 x가 존재하지 않는다. 따라서 상위 지역(아래 예제의 경우 전역)에서 변수 x를 찾고 존재하지 않으면 변수 x를 암묵적으로 전역변수로 선언한다.


function foo() {
  x = 1;   // Throws a ReferenceError in "use strict" mode
  var y = 2;
}

foo();

console.log(x); // 1
console.log(y); // ReferenceError: y is not defined

의도하지 않게 전역변수가 되었다면 혼란의 여지가 있으므로 var keyword는 반드시 사용하자.


Lexical scoping (Static scoping)

자바스크립트는 함수가 선언된 시점에서의 유효범위를 갖는다. 예제의 함수 bar가 어떤 상황에서 호출될 지 선언 시점에서는 알 수 없다.


var i = 5;

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

function bar() { // 선언된 시점에서의 scope를 갖는다!
  console.log(i);
}

foo(); // ?




참고한 사이트


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함