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. 감사합니다!!
  2. 김성희
    전역변수가 왜 위험한지, 익명함수를 왜 쓰는지를 알게 됐습니다. 감사합니다.
  3. anonymous
    정말 많이 배우고 있습니다. 자바스크립트 사용하면서도 제대로 알지도 못했던 게 너무 많네요..
    이해도 너무 잘되요 감사합니다.
    정말 초급수준의 코딩만 하다보니 함수가 선언된 시점에서 유효범위를 갖는다는 사실을 처음 알았어요...
    아니면 제가 공부하면서 책에서 몇번이나 공부했던 내용일수도 있는데 그땐 저 말이 무슨 의민지 잘 몰랐겠죠..
    아무튼 정말 도움이 많이 되고 이해도 너무 잘되게 설명잘해주시네요
  4. sssjunn
    감사합니다.
  5. 호호
    전역변수와 지역변서 첫번째 강의 들었는데 궁금하게 있는데요
    변수부분 공부할때 처음 변수만들때는 var 쓰고 변수값 바꿀때는 이미 변수를 생성했으니
    var을 안쓰고 바로 변수 = 값 써도 된다고 하셨는데

    var vscope = 'global'
    function fscope(){
    vscope = 'local';

    }
    fscope();

    여기서도 변수값을 바꾼다는 의미로 봐도 되나요??
  6. Seo Yun Seok Tudoistube
    함수의 블록에서만 지역변수이고, 나머지는 전역변수로 보면 되는거였네요. 감사합니다^_____^!!!
  7. Sk Shin
    감사합니다. ^^
  8. 리느
    감사합니다.
  9. crable
    감사합니다.
  10. 이승우
    20170516 완료
  11. 고베베
    와 감사합니다 두 분. 저도 그게 궁금했거든요!!!!
    다른 존재이기에 불러올 수 없어서 호출이 안되는거군요!
    대화보기
    • 최규선
      20170428 완료
    • 신입1
      감사합니다
    • richblue
      1/5 전역변수 와 지역변수
      JS는 함수형언어
      함수는 모듈화 근간, 코드 재사용 , 정보 구성, 정보 은닉 , 행위 지정
      함수안 변수는 var 키워드를 사용해서 지역변수로 선언하자.
      똑같은 이름의 변수를 다른 의미로 사용할 수 있다.
    • 전성욱
      자바스크립트 구조 특성상 함수를 실행하기전 변수의 선언부분만 먼저 읽고 나머지 코드를 읽는 방식을 가지고 있습니다

      alert(a)
      var a = 1;

      이런 코드나 함수가 있으면

      var a
      alert(a)
      a = 1
      컴퓨터는 다음과 같이 읽기때문에 변수 네이밍 오류를 출력하지 않고 변수를 정의하지 않은 var의 값 undefined 를 가져오게 됩니다
      대화보기
      • 전성욱
        자바스크립트 변수는 var 생성자의 유무에 따라 같은 이름의 변수라도 사용할 수 있는 범위가 달라진다
        이것을 자바스크립트의 유효 범위가 다르다고 하는데 유효범위에 따른 변수의 종류에 대한 구분은 지역변수와 전역변수로 나눠진다
        함수 밖에서 선언한 var로 변수는 전역변수가 되며, 함수블럭 내에서 var로 선언한 변수는 지역변수가 된다.
        지역변수는 같은이름의 지역변수가 존재해도 다른 객체로 취급되어 변수명의 재사용성이 훨씬 높아진다
        지역젼수는 수명이 짧아 선언된 위상의 코드블럭이 종료되면 자동으로 사라진다
        전역변수는 보안과 가독성을 높이기 위해 보통 사용하지 않는다
        전역변수를 사용하고 싶을때 익명함수를 이용해 전역변수를 모아놓은 하나의 객체로 선언한다. 이것은 이전 강의의 모듈화에 이어지는 내용이다
        자바스크립트는 함수가 선언된 시점에서 유효범위를 가진다. 블록안에서 함수를 호출해도 그 블록의 지역변수를 가져오지 않는다
      • function a (){
        var i = 0;
        }
        에 있는 변수 i와
        for(var i = 0; i < 5; i++)에 있는 변수 i는 변수명만 같은뿐 다른 존재라고 보면 될거같아요.
        대화보기
        • 밍구르르밍
          아 var i =0;가 지역변수라서 다른곳에서는 쓸수없으니 a();를 호출한구문은 사실상 아무것도 호출하지 못하셔 그냥

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

          이 구문만 남게되어 01234가 나오는 것 일까요? 자문자답했네요..
          대화보기
          • 밍구르르밍
            function a (){
            var i = 0;
            }
            for(var i = 0; i < 5; i++){
            a();
            document.write(i);
            }

            이것도 var i =0; 으로 계속 초기화 시켜주는거 아닌가요? 지역변수여도..
          • @박

            i가 1씩 증가하고 5보다 작을때까지 반복인데
            a()가 계속 i를 0으로 초기화시키니

            무한반복이 이뤄지는거죠!
          • function a (){
            i = 0;
            }
            for(i = 0; i < 5; i++){
            a();
            document.write(i);
            }

            이게 무한 반복을 발생하는 이유는 뭘까요? 이해가 잘 안 돼서...
          • 임지호
            전역변수/지역변수 : 함수 바깥에서 선언된 변수(전역적으로 영향을 미침)/함수 내에서 선언된 변수(함수 내에서만
            영향을 미침)
            - 전역변수는 거의 쓰이지 않음(프로그램이 커질수록 변수의 이름이 서로 헷갈릴 수 있기 때문. 이런 개념도 그러
            한 문제때문에 고안된 것)
            - 함수 밖에서 var를 쓰면 전역변수, 함수 안에서 var를 쓰면 지역변수
            - 전역변수를 딱 하나만 쓰려면 전역변수 하나를 객체로 만들고 그 소속 아래 나머지 변수를 선언한다.
            - 전역변수를 쓰지 않으려면 만든 로직을 익명함수화한다(모듈화의 기초)
            - 자바스크립트의 지역변수는 {}가 아니라 함수!에서만 유효하다.
            - 자바스크립트는 정적 유효범위를 채택한다(함수 호출시점이 아니라 선언 시점을 기준으로 한다)
          • 히스토
            마지막 수업방식이 재밌네요. 문제 내주고 알아맞추기 ㅋㅋ
          • 서비
            잘보고 갑니다...
          • 정요한
            퍼갑니다 . ^^
          • 김명수
            정적 유효범위! 잘 들었습니다. 감사합니다.
          • 날고기는람쥐
            var i = 5;
            function a(){
            var i = i;
            document.write(i)
            b();
            }

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

            전역변수로 지정된 i가 5라는 값을 가지고 있으면서 함수 a 에선 자기 자신 i를 지역변수로 가져버리게 되는데
            거기서 undefiend가 나오게됩니다.

            그리고 함수 b에서 i를 호출했기에 5도 출력이 됩니다.

            즉 두번 출력이 되어버리는것이죠
            실제로 함수 b에서 document.write(i); 를 document write(' a ' + i ) 바꾼다면 결과는 undefined a 5 가 됩니다.

            제 생각이 틀린것이라면 수정 답변을 달아주세요. 저두 정확한 답을 알고 싶네요.
            대화보기
            • 완료!
              완료! 감사합니다.
            • 감사합니다. 정리가 잘 됐습니다.
            • 취준생1
              오 사용될 때 정의될 때 이렇게 생각하니까 쉽군요...
            • yihsang
              감사합니다.
            • kmax95@naver.com
              ㅋㅋㅋㅋ
              대화보기
              • Harry S. Hur
                앵귤러를 공부하기 위해 보고있습니다. 감사합니다.
              • fasdgoc
                자바스크립트는 함수에 대한 유효범위만을 제공한다.
                전역변수는 객체로 묶는다 (익명함수 내부)
                자바스크립트는 함수가 선언된 시점에서의 유효범위를 갖는다.
              • interimlife
                이 아이가 누구의 아이인가!!!!
                여러분, 전역변수가 이러케 무섭슴니다.
              • 이주환
                2016. 04. 24
                유효범위는 정말 중요한 내용입니다.
              • JustStudy
                고맙습니다
              • 삼십대학생
                점점 어려워지는군요. 하... 여기서 거의 포기할뻔 했지만, 약 2주만에 다시 돌아왔습니다. 다시 정신차리고 열심히 하겠습니다. ㅠㅠ 화이팅...
              • 공부합시다
                처음에 MYAPP 이라는 이름의 변수이름을 만들었습니다.
                1. 함수 밖에서 만들었기에 MYAPP 는 전역 변수가 됩니다.
                (참조:1/5 영상 처음에 설명되어 있습니다. 함수 밖에서 변수를 선언하면 그 변수는 전역변수가 된다.)
                2. MYAPP 이라는 전역변수도 싫어 다시 함수(익명) 로 만들었기때문에 더 이상 전역변수가 아닌
                지역 변수가 되었습니다.
                3. 다시 myappfn 변수를 만들고 거기에 익명함수를 객체로 만들었으니
                myappfn은 다시 전역 변수가 된것이죠
                이해가 되셨을까요 ?

                저는 양파를 생각 했습니다. 양파를 생각하시면 어떨까요 ? !
                대화보기
                • basicb
                  3번째 동영상에서 'myappfn 이라는 함수의 이름도 사실은 변수 안에 함수가 들어가 있는 것이기 때문에 결국에 myappfn이 전역 변수가 된다' 라는 말이 이해가 안가네요. 혹시 설명 해주실분 계신가요?
                • Byeong Koo Kang
                  정적 유효범위가 신박하네요!
                • 질문이용!!
                  질문 있습니다.
                  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());
                • 김경민
                  이렇게 클로저를 안써도 함수를 바로 실행하도 되는 방법이 있네요!

                  <script>
                  var arr = [];
                  for(var i = 0 ; i < 5; i++)
                  {
                  arr[i] = (function() {
                  return i;
                  }());
                  }

                  for(var index in arr)
                  console.log(arr[index]);
                  </script>
                • Kyung Jun Jung
                  자답입니다.
                  호이스팅 때문에 그렇게 됩니다. ^^
                  대화보기
                  • Kyung Jun Jung
                    좋은 강의 잘 듣고 있습니다.
                    하기의 내용이 궁금하여 로그인하게 되네요...

                    <script>
                    function fn1(){
                    alert(x);
                    }

                    fn1();

                    var x = 20;
                    </script>

                    이건 undefined alert 이 뜹니다.

                    <script>
                    function fn1(){
                    alert(x);
                    }

                    fn1();

                    x = 20;
                    </script>

                    이건 alert 이 안뜹니다.

                    차이는 전역변수 x 의 var 가 있고 없고 인데.. 무슨 이유로 이런 현상이 발생하는지요?

                    혹시 아시는 분 알려주세요~~
                  • 리치
                    scoping 강의 감사합니다.
                  • 리치
                    scoping 강의 감사합니다.
                  • Beluga
                    더글라스 크로포드의
                    "JavaScript 핵심 가이드"
                    대화보기
                    • 어디선가... 책 이름 언급한거 같은데... 뭐였죠? ㅠ
                    • QuiDam
                      일단 개념만 갖고 갑니다. ^^
                      매번 감사합니다.
                    버전 관리
                    egoing
                    현재 버전
                    선택 버전
                    graphittie 자세히 보기