JavaScript

유효범위

유효범위(Scope)는 변수의 수명을 의미한다. 아래의 예제를 보자. 결과는 global이다.

var vscope = 'global';
function fscope(){
	alert(vscope);
}
fscope();

함수 밖에서 변수를 선언하면 그 변수는 전역변수가 된다. 전역변수는 에플리케이션 전역에서 접근이 가능한 변수다. 다시 말해서 어떤 함수 안에서도 그 변수에 접근 할 수 있다. 그렇기 때문에 함수 fscope 내에서 vscope를 호출 했을 때 함수 밖에서 선언된 vscope의 값 global이 반환된 것이다. 아래 예제를 보자. 결과는 '함수안 local'과 '함수밖 global'이 출력된다.

var vscope = 'global';
function fscope(){
    var vscope = 'local';
	alert('함수안 '+vscope);
}
fscope();
alert('함수밖 '+vscope);

즉 함수 안에서 변수 vscope을 조회(4행) 했을 때 함수 내에서 선언한 지역변수 vscope(3행)의 값인 local이 사용되었다. 하지만 함수 밖에서 vscope를 호출(7행) 했을 때는 전역변수 vscope(1행)의 값인 global이 사용된 것이다. 즉 지역변수의 유효범위는 함수 안이고, 전역변수의 유효범위는 에플리케이션 전역인데, 같은 이름의 지역변수와 전역변수가 동시에 정의되어 있다면 지역변수가 우선한다는 것을 알 수 있다. 아래 예제를 보자. 결과는 모두 local이다.

var vscope = 'global';
function fscope(){
    vscope = 'local';
    alert('함수안'+vscope);
}
fscope();
alert('함수밖'+vscope);

함수밖에서도 vscope의 값이 local인 이유는 무엇일까? 그것은 함수 fscope의 지역변수를 선언할 때 var를 사용하지 않았기 때문이다. var를 사용하지 않은 지역변수는 전역변수가 된다. 따라서 3행은 전역변수의 값을 local로 변경하게 된 것이다. var을 쓰는 것과 쓰지 않는 것의 차이를 이해해야 한다.

전역변수는 사용하지 않는 것이 좋다. 여러가지 이유로 그 값이 변경될 수 있기 때문이다. 함수 안에서 전역변수를 사용하고 있는데, 누군가에 의해서 전역변수의 값이 달라졌다면 어떻게 될까? 함수의 동작도 달라지게 된다. 이것은 버그의 원인이 된다. 또한 함수를 다른 에플리케이션에 이식하는데도 어려움을 초래한다. 함수의 핵심은 로직의 재활용이라는 점을 상기하자. 변수를 선언할 때는 꼭 var을 붙이는 것을 습관화해야 한다. 전역변수를 사용해야 하는 경우라면 그것을 사용하는 이유를 명확히 알고 있을 때 사용하도록 하자.

유효범위의 효용

아래 두개의 예제는 변수 i를 지역변수로 사용했을 때와 전역변수로 사용했을 때의 차이점을 보여준다. 전역변수는 각기 다른 로직에서 사용하는 같은 이름의 변수값을 변경시켜서 의도하지 않은 문제를 발생시킨다.

지역변수의 사용

function a (){
    var i = 0;
}
for(var i = 0; i < 5; i++){
	a();
	document.write(i);
}

 실행결과

01234

전역변수의 사용

본 예제는 무한반복을 발생시킨다. 
function a (){
    i = 0;
}
for(i = 0; i < 5; i++){
	a();
	document.write(i);
}

전역변수의 사용

불가피하게 전역변수를 사용해야 하는 경우는 하나의 객체를 전역변수로 만들고 객체의 속성으로 변수를 관리하는 방법을 사용한다.

MYAPP = {}
MYAPP.calculator = {
    'left' : null,
	'right' : null
}
MYAPP.coordinate = {
	'left' : null,
	'right' : null	
}

MYAPP.calculator.left = 10;
MYAPP.calculator.right = 20;
function sum(){
	return MYAPP.calculator.left + MYAPP.calculator.right;
}
document.write(sum());

전역변수를 사용하고 싶지 않다면 아래와 같이 익명함수를 호출함으로서 이러한 목적을 달성할 수 있다.

(function(){
    var MYAPP = {}
	MYAPP.calculator = {
		'left' : null,
		'right' : null
	}
	MYAPP.coordinate = {
		'left' : null,
		'right' : null	
	}
	MYAPP.calculator.left = 10;
	MYAPP.calculator.right = 20;
	function sum(){
		return MYAPP.calculator.left + MYAPP.calculator.right;
	}
	document.write(sum());
}())

위와 같은 방법은 자바스크립트에서 로직을 모듈화하는 일반적인 방법이다. 

유효범위의 대상 (함수)

자바스크립트는 함수에 대한 유효범위만을 제공한다. 많은 언어들이 블록(대체로 {,})에 대한 유효범위를 제공하는 것과 다른 점이다. 아래 예제의 결과는 coding everybody이다.

for(var i = 0; i < 1; i++){
    var name = 'coding everybody';
}
alert(name);

자바에서는 아래의 코드는 허용되지 않는다. name은 지역변수로 for 문 안에서 선언 되었는데 이를 for문 밖에서 호출하고 있기 때문이다.

for(int i = 0; i < 10; i++){
	String name = "egoing";
}
System.out.println(name);

자바스크립트의 지역변수는 함수에서만 유효하다.

정적 유효범위

자바스크립트는 함수가 선언된 시점에서의 유효범위를 갖는다. 이러한 유효범위의 방식을 정적 유효범위(static scoping), 혹은 렉시컬(lexical scoping)이라고 한다. 

var i = 5;

function a(){
    var i = 10;
	b();
}

function b(){
	document.write(i);
}

a();

실행 결과는 5이다.

댓글

댓글 본문
  1. 손보선
    C/C++/C#/Java 등을 하다가 자바스크립트를 공부하면서 var 는 진짜 없어져야 한다는 생각을 많이 합니다.
    당장 편할진 몰라도 구조적인 코딩을 하는데 엄청 제약이 생깁니다.
    혹시 var 을 여전히 사용한다면 이제라도 let 을 이용합시다!
  2. 드림보이
    수강완료했습니다...
  3. 낭만고양이
    수강완료
  4. GelandeWagen
    210621 ok
  5. Amousk
    좋은 강의 감사합니다.
  6. coding_prince
    감사합니다.
  7. 정적유효범위 헷갈려여여~~
  8. 어렵네요.....듣긴 들었는데 다음에 또 들어야지..
  9. 앙냥냥
    2021.04.04 ~ 2021.04.05 봐씁니다!!
  10. 금도끼은도끼
    정적유효 범위강좌에 대해 보충 예제입니다..(예제 1과 2를 비교해보세요)
    (예제1 의 a, b, c값은?)-->b값에 중점을 두고봐보세요..그러면 정적유효범위강좌가 다시보일거에요..
    <script>
    var a = 10;
    var b = 20;
    var c = 30;
    function outer_func() {
    var b = 200;
    var c = 300;

    inner_func();
    }
    function inner_func() {
    var c = 3000;
    document.write(a + "<br />");
    document.write(b + "<br />"); //b 값이 20이 출력됨
    document.write(c + "<br />");
    }
    outer_func();
    </script>
    <예제 2의 a, b, c값은? > b값이 다른이유가 보이시나요??
    <script>
    var a =10;
    var b=20;
    var c=30;
    function outer_func(){
    var b=200;
    var c=300;
    function inner_func(){
    var c=3000;
    document.write(a+"<br />");
    document.write(b+ "<br />"); //b값이 200 이 출력됨
    document.write(c + "<br />");
    }
    inner_func();
    }
    outer_func();
    </script>
  11. Asanagi
    2021.03.22 완료
  12. JS의 유효범위는 함수만을 기준으로 함.(ex.반복문 같은경우 나오면 사라짐)
  13. hanel_
    복잡해서 어렵네요. 감사합니다..
  14. 잘 봤습니다
  15. gf0308
    이번에도 감사합니다 선생님 :)
  16. 주니어개발자
    사실 지금부터가 진정한 앙꼬
  17. 해킹잘하고싶어요ㅎ
    (21/01/06) C를 배우는 과정에서 유효범위에 대한 내용을 어느정도 인지하고 왔는데 자바스크립트는 뭔가 다른 느낌이네요.. 앞으로 자바스크립트로 프로그래밍을 해보면서 유효범위에 관한 지식이 필요할 때 다시 와야겠어요..
  18. switpotato
    20201213 완료
  19. 20201210
  20. psyless
    20201201
  21. 강승
    감사합니다
  22. 박병진
    2020.10.22 감사합니다.
  23. 당근조아
    201018완
  24. 20201012 완료
  25. 코딩지니어스
    201010 완료
  26. 김준석
    20.07.28 학습완료
  27. 준식
    20200606 진행중
  28. 아기별
    이고잉선생님 항상 감사합니다 ^_^ 공부인데 뭔가 재미있어요!!!!
  29. 아기별
    감사합니다! 덕분에 익명함수에 대한 이해가 더 쉬워졌어요
    대화보기
    • ironia
      잘 봤습니다~
    • 뿡뿡팡야
      완료
    • 이고잉2세
      이번 강의를 보시는 분들은 이 점을 참고해주셨으면 좋곘습니다 !! 이고잉님의 강의를 많이 들어본 학생으로써 감히 꼬잉님의 대답이 이렇지 않을까하여 몇줄 적어봅니다.

      1. var는 현재 자바스크립트 문법체계에서는 거의 사장된 친구다
      2. 현재는 var의 단점을 상당히 보완한 let이라는 친구가 주로 쓰인다. ( ex. let egoing = 1 )
      3. 그러면 var을 뭣하러 배우냐? 딱 2가지 생각해보면 다음과 같다.
      3-1. let이라는 친구가 주류로 채택되기 전 상당수 많은 자바스크립트 언어들이 var로 구현되었기 때문에 결국 우리는 알아야한다. 그래야 회사들어가서 남이 짠 코드안에 var 보면서 투덜대면서 이해할 수 있다.
      3-2 let이라는 좋은 친구가 나오게 된 배경인 var와 자바스크립트의 이전 문제점을 파악해보며 관련된 여러가지 이해해야 할 유용한 개념들이 있다.

      저도 굉장히 부족한 놈이라 나름 검색하면서 정리해봤네요. 열공!!

      ps. 아참 결국 let은 공부하셔야 합니다. var를 쓰레기 취급만 하지 말자는 이야기이죠 ㅎ
    • moleskindiary@gmail.com
      감사합니다!
    • Jess
      2020.02.9
      어렵네요 zz
      좋은강의 감사드립니다.
    • 현수
      감사합니다
    • ㅇㅇ
      유효(4/5)부터 시작하기
    • 걍걍
      var, let, const에 대한 내용도 업데이트가 되어야 할 것 같네요
    • Blanc
      2020.01.11
    • Coder
      유효범위 1/5 영상에서 함수 fscope() 에는 alert같은 기능이 딱히 없는데, fscope(); 를 쓰신 이유가 무엇인가요??
    • 굼벵이
      완료
    • 오현주
      2019.12.17 수강
    • YJYJ
      4번영상 이제 수정 필요하지 않나요? 이제 let 키워드 이용해서 block scope 이용가능한걸로 알고있습니다.
      function a(){
      for (let i = 0; i<3; i++){
      let j = 'outer block scope';
      {
      let j = 'inner block scope';
      console.log('in the block: ', j);
      }
      console.log('out of the block: ', j)
      }
      }
      이 예제에서 출력이
      //in the block: inner block scope
      //out of the block: outer block scope
      //in the block: inner block scope
      //out of the block: outer block scope
      //in the block: inner block scope
      //out of the block: outer block scope
      이런식으로 나와요
    • 홍주호
      20191019 완료
    • 박창신
      완료
    • 행복한유령
      3/5 19-07-31
    • 자스
      (function(){..}()) == (function(){..})();
      위에 익명함수 선언과 호출 표현 둘다 표현 동일 한가요?
    • sonypark
      이고잉님 설명 덕분에 막연히 이해했던게 명확해졌습니다. 감사합니다!!
    • 박정환
      차근차근 정말 잘 가르치시네요.
      예전에 포기했던 자바스크립트를 이제야 이해하고있습니다.
      ES6 강의 업데이트도 부탁드립니다.
    • polo
      함수작성 방법에 대하여 질문
      함수작성후 ;(세미클론)을 빼야 하지 않는지요?
      대화보기
      • 쌀쌀
        너무 감사합니다 ㅜㅜ
      버전 관리
      egoing
      현재 버전
      선택 버전
      graphittie 자세히 보기