시작하기 전에
이 튜토리얼을 공부하기 위한 가장 좋은 방법은 파이어폭스와 파이어버그를 바로 곁에 두는 것입니다. 이 방법으로 본 튜토리얼내의 예제를 즉시 테스트 해볼 수 있습니다.
만약 아직 가지고 있지 않다면 두 가지 모두 설치 하세요.
정의
scope
1. (명사) 어떤 활동 혹은 작업 또는 힘을 가지거나 제어를 할 수 있는 지역 [1]
2. (명사) 프로그램 내에서 변수의 접근
범위; 예를 들어 어떤 함수가 다른 함수에서 생성된 변수를 사용할 수 있는지 여부. [2]
함수 실행 시 어디에 있는 변수에 접근이 가능 한지 찾는 중에 누군가가 "이건 스코프 문제야" 혹은 "이건 잘못된 스코프에서 실행 중이야"
라고 하거나 그와 비슷하게 이야기를 하면 우리는 어떻게 이것을 처리해야 할까요?
이제 가봅시다
사실 자바스크립트 내에서 선언된 함수들은 객체에 소속된 메소드들 입니다. 아래와 같이 코드를 작성하더라도 말이죠:
function fn() {
alert(11);
}
제가 농담을 하고 있다고 말하시겠죠. 하지만 이게 진짜 진실인지 아주 쉽고 간단하게 증명 해낼 수 있습니다. 이 예제를 위해서 어떠한
자바스크립트 파일이나 서버, 혹은 html이 필요치 않습니다. 단지 파이어폭스를 열고 파이어버그의 하단 윈도우를 열어서 콘솔 탭을 클릭하고
브라우저의 status 바 바로 위에 >>> 입력란에 코드를 입력하면 됩니다.
아래와 같이 입력하고:
function fn() { alert(11); };
엔터를 입력하면 아무 반응이 없습니다. 그렇죠? fn 함수만 선언 한 것이지요. 다음과 같이 입력합니다:
fn();
엔터를 입력하면 11이 적힌 경고 창을 볼 수 있습니다. 여기까지 잘 따라 오셨습니다. 다시 입력해봅시다:
window.fn();
this.fn();
같은 결과가 보이나요? 함수 fn은 window 객체의 메서드가 된 것을 알 수 있고 두 번째 라인은
this 변수가 window 객체를 가리키고 있다는 사실을 증명합니다. 이런고로 자신의 함수를
window.myFunction(...)처럼 호출할 필요가 없다는 것이죠. 이것은 편리하기도 하고 게으른 프로그래머들의 일을 덜어줍니다.
window 객체
window 객체는 항상 존재하며 브라우저 윈도우 그 자체 라고 생각 하시면 됩니다. 이것은
document 객체와 전역(global)으로 선언된 모든 변수와 같은 다양한 객체를 담고 있습니다.
다시 파이어버그를 열어서 script 탭으로 변경 시키고 우측에 "New watch
expression..." 라고 적혀 있는 박스에 window 라고 입력 합니다. 그러면 window 객체에 어떤
것들이 있는지 살펴 볼 수 있습니다.
특히 방금 전 선언했던 fn 함수를 찾아 보시기 바랍니다.
각각의 frame 혹은 iframe은 자신만의 고유한 영역에서 독립적인 window 객체를 가지고 있습니다.
스코프(scope) 이해하기
이제 조금 더 어려운걸 해봅시다. 다시 파이어버그의 Console 탭을 선택하고 다음과 같이 입력합니다:
var o1 = {testvar:22, fun:function() { alert('o1: ' + this.testvar); }};
var o2 = {testvar:33, fun:function() { alert('o2: ' + this.testvar); }};
우리가 무엇을 한 것일까요? 객체 o1 과 o2 를 선언했고 이 둘은 같은
이름의 프로퍼티와 메서드를 가지고 있지만 각각의 프로퍼티는 다른 값을 가지고 있습니다.
아래와 같이 입력합니다:
fun();
window.fun();
this.fun();
에러가 발생하지요? 좋습니다. window 객체(this와 동일)는 fun 메소드를 가지고 있지 않습니다. 아래와 같이 해보세요:
o1.fun();
o2.fun();
이제 22와 33이 보이죠? 아주 좋습니다!
이제 이 복잡한 부분의 마지막입니다. 지금까지는 간단한 함수들을 사용했고 그래서 개별 객체의 타입(type)에 대해서 신경 쓸 필요가
없었습니다. 하지만 o1.fun 이 아주 기능이 많고 지난주부터 작업해서 이제 마지막 작업 단계에 있다고 칩시다. 코드 내에 산재해 있는
this 변수가 100 라인 정도 된다고 상상해 보자 구요. o1.fun을 호출(실행)시
this가 o2를 가리키고 있다면 어떻게 해결해야 할까요? 아래와 같이 입력해봅시다:
o1.fun.call(o2);
o1의 fun 메소드가 실행 중 일 때 강제로 변수 this 가 o2를 지정되게 설정된걸 보셨나요? 좀더
유식하게 말하면 다음과 같습니다: 메소드 o1.fun이 객체 o2의 스코프(scope)내에서 실행 된다
정리하면 스코프는 어떤 객체의 메서드로서 함수가 실행 중 일 때 this 변수의 값이다 라고 생각하시면 될
것 같습니다.
변수의 가시범위(Visibility)
변수의 가시범위는 이전 단락인 스코프 항목과 밀접한 관계에 있습니다. 우리는 이미 변수(함수를 포함한 모든 변수)가 어떤 객체나 함수 밖에
선언되면 전역으로 등록 된다고 알고 있습니다. 기술적으로 다시 말하면 window 객체의 전역 프로퍼티가 되는 것이지요.
전역 변수들은 어디에서든지 보입니다;어떤 함수들의 안에서든 밖에서든. 만약 하나의 함수에서 전역 변수를 수정하게 되면 다른
함수들은 변경된 값을 보게 됩니다.
이제 객체가 자신만의 고유한 프로퍼티(앞서 testvar 예제처럼)를 갖는다는 걸 알 수 있게 되었습니다.
이것은 객체의 안과 밖에서 접근 가능한데, 맞는지 직접 시험해 봅시다:
alert(o1.testvar); // o1의 프로퍼티인 testvar를 외부에서 접근
내부에서 접근하는 것은 아까 두 개의 fun 메소드 시연에서 이미 해봤으므로 그냥 넘어 갑니다.
이제 마지막으로 남은 퍼즐의 조각은 지역 변수는 함수 내에서 var 키워드와 같이 선언 되어야 한다는
겁니다:
i = 44;
function fn2() {
var i = 55;
alert(i);
}
fn2();
어떤 것을 보았나요? 55 이지요. 변수 i 는 fn2 내에 선언 되어 fn2의 지역 변수가 되었고 44가
들어있는 전역 변수인 i 에 접근하지 않습니다.
하지만 이렇게 하면:
alert(i);
전역 변수 i 에 접근하기 때문에 44가 나오는 것을 볼 수 있습니다.
이 문서가 스코프와 변수 가시범위 공부에 많은 도움이 되길 바랍니다.
더 읽을만한 것들: