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. 이승우
    20170516 완료
  2. 고베베
    와 감사합니다 두 분. 저도 그게 궁금했거든요!!!!
    다른 존재이기에 불러올 수 없어서 호출이 안되는거군요!
    대화보기
    • 최규선
      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
                      일단 개념만 갖고 갑니다. ^^
                      매번 감사합니다.
                    • Simon Lee
                      10~12번째 줄의
                      -----함수밖에서도 vscope의 값이 local인 이유는 무엇일까? 그것은 함수 fscope의 지역변수를 선언할 때 var를 사용하지 않았기 때문이다. var를 사용하지 않은 지역변수는 전역변수가 된다. 따라서 3행은 전역변수의 값을 local로 변경하게 된 것이다. var을 쓰는 것과 쓰지 않는 것의 차이를 이해해야 한다-----

                      라는 부분은, 함수안에서 var 없이 사용한 vscope는 새로 선언한 지역변수가 아니라, (함수밖에서 선언된 같은이름의)전역변수인 vscope가 사용된 것이다. 라고 설명하는 게 더 자연스럽지 않을까요?
                    • 준맹
                      좋은 강의 감사합니다. 다음에 와서 또 봐야될 것 같습니다. 저는 아직도 모호한 부분이 있네요:(
                    • 우후훗
                      아 참고로 처음 생각하셧던 대로 지역변수 i에 전역변수 5를 설정해주시려거든
                      var i = i 를 var i = this.i로 수정하시면 됩니다. this는 자바와 동일하게 사용되네요
                      대화보기
                      • 우후훗
                        화질구지님의 대한 답변...이라기엔 너무 늦은거 같지만 어쨋든 다른 궁금한 분이 보실수도 있으므로..
                        본문의 강의 내용중에 이런 내용이 있었죠.
                        '같은 이름의 지역변수와 전역변수가 있을 경우 지역변수가 우선한다'
                        위 내용을 생각하고 화질구지님의 소스를 보면,
                        var i = 5; // 전역변수 i, 값은 5

                        function a(){
                        var i = i; // a라는 함수내부에서 선언되었으니 var i는 지역변수를 선언함이고 그값으로 준 i는 우선순위에 따라 전역변수 i가 아닌 지역변수 i가 되는겁니다. 즉 추측하신것처럼 지역변수의 값이 정의되지 않았으므로 undefined가 됩니다
                        document.write(i) //그래서 첫번째 출력결과는 undefined가 나옵니다.
                        b();
                        }

                        function b(){
                        document.write(i); //함수 b의 내부에는 i라는 지역변수가 존재하지 않습니다. 고로 출력하는 i는 전역변수 i, 즉 5가 됩니다. 그래서 두번째 출력결과는 5가 되겠습니다.
                        }

                        a();

                        결과적으로 a()의 write(i)는 undefined, b()의 write(i)는 5가 되므로

                        출력결과로 undefined5가 나오게 됩니다
                      • 이원배
                        자바스크립트에서 함수를 선언할때
                        function statement 방식과 function expression 방식이 있는데
                        (Function() 생성자 함수를 사용한 방법도 있습니다)
                        function statement 방식은

                        흔히 함수를 선언하는
                        function a()
                        {
                        함수식;
                        }

                        방식이고

                        function expression 방식은
                        변수를 선언해서 함수를 대입하는 방식입니다.

                        var a = function(){};

                        이런씩으로 생성이 되는데

                        여기서 또 함수의 접근 범위가 달라집니다.


                        a();

                        function a()
                        {
                        alert(1);
                        }

                        이런씩으로 함수 선언보다 앞에서 함수를 호출하면 호출이 됩니다.
                        하지만

                        a();

                        var a = function()
                        {
                        alert(1);
                        }
                        이런씩으로 function expression 방식으로 함수를 선언하게 되면
                        함수 호출을 막아줍니다.
                        그래서 이런씩으로 함수를 선언하라고 권고 하고 있고요

                        이런 현상은 함수 호이스팅 이라고 하는데.

                        네..

                        그냥 아는척 하고 싶어서요... 뎨헷
                      • 강집사
                        오호 유효범위...
                        자바를 먼저 공부해서 그런진 살작 햇갈리네요..ㅜㅜ
                        그래도 한번더 들어보고 개념을 잡고 갑니다.

                        감사합니다 ^^
                      • document.write
                        var i=5; 전역변수 i 값은 5
                        function a(){
                        var i=i; 지역변수 i 값은 할당되지 않았으므로 undefined i에 undefined 대입
                        document.write(i); 지역변수 i undefined 출력
                        b();
                        }
                        이럴것 같은 저 개인적인 생각입니다.
                        자바스크립트 콘솔창에서 var i=5; 이렇게 해서 엔터치면 number가 아니라 undefined 가 뜨더라구요 i;이렇게해서 엔터치면 5가 뜨고
                        우리가 생각하기에는 5하면 데이터가 숫자라고 알지만 컴퓨터인 자바스크립트는 일단은 테이터형이 undefined 정의되지 않은 값이다. 이렇게 인식하도록 설계가 된듯하네요^^
                        대화보기
                        • Anna Kim
                          네.

                          일단 var i =i 라고 지정해주었지만 i에게 구체적으로 숫자나 스트링같은 정의된것이 없어서 undefined가 된걸테구요,
                          말씀대로 a 함수안에서 스스로를 참고하고나서 document.write(i) 이 디스플레이해달라고 요구했기때문에 undefined라고 뜨고 나서 b함수가 호출되어 5라고 디스플레이 됬어요. egoing님이 주신 예제또한 a 함수안에서 var i가 정의되어 참고가 된 상태이지만 그 변수에 대한 호출메소드가 없어서(document.write 같은...) 콘솔에 뜨지않은것 뿐이에요.

                          만일 화질구지님의 예제에서
                          a 함수안에서 var i = i; 를 var i = 3; 으로 숫자를 지정해 정의해준다면 결과는
                          35로 뜨게 됩니다. 즉, 함수a 를 처리해서 호출한 후 함수 b를 처리해 불러왔다는 뜻이 되겠네요.

                          결론은 호출메소드가 있느냐없느냐 여부이지 궁극적으로는 함수안의 모든 내용은 다 참고되고 있다는 사실입니다.
                          대화보기
                          • 화질구지
                            너무 잘 보고 있습니다~
                            수업을 듣다가개인적으로 궁금한게 생겨서요.

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

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

                            이런식으로 코드를 작성해봤는데, 답은 'undefined5'으로 나오게 되네요.
                            개인적인 생각으로는 a()에서 i 생성시 전역변수인 5값을 가지고 있는 i가 들어오게 될 것 같았는데 정의되지 않음으로 뜨게되네요. 이 경우는 어떻게 처리되는건지 혹시 알 수 있을까요? a()내부에서 var i를 통해 먼저 i가 생성된 상태이기 때문에 뒤에 =i;에서 자기 스스로를 참고하게 되는건가요?
                          버전 관리
                          egoing
                          현재 버전
                          선택 버전
                          graphittie 자세히 보기