프로그래밍

자바스크립트 window객체와 효율적인 변수 선언법

Jay22 2017. 2. 15. 21:29
반응형

자바스크립트는 브라우저 환경에서 돌아가도록 만들어졌다. 그래서 글로벌 영역을 다른 언어와는 조금 다르게 구현하고 있다. 그래서 조금 다른 개념이 들어가 있다. 


글로벌 영역도 하나의 변수로 정의한다.


글로벌 영역은 window객체가 관장한다. 표준에서 말하기를, 


1. 글로벌 객체(Global Object)는 단 하나만 유일하게 존재하며, 어떠한 컨텍스트가 실행되기 전에 먼저 생성된다. 


2. 글로벌 객체는 내부적으로 생성자가 없으며 new를 이용해서 생성자로서 사용할 수 없다.


3. 글로벌 객체는 내부적으로 함수가 없으며, 글로벌 객체를 함수로서 호출할 수 없다.


4. 글로벌 객체의 프로토타입은 구현방법에 따라 달라질 수 있다.


5. HTML DOM 환경에서 이 객체는 window 속성을 가지고 있으며, 이것이 Global Object 자체를 나타낸다.


<script>

    var global = "global";

   

    console.log(window.global);

    console.log(global);

</script>



이런식으로 글로벌 변수를 만들고 window속성으로 접근할 수 있다.



window 객체를 이용한 반복문


<script>

    var i;

    

    for(i=1; i<5; i++) {

        window["button"+i] = document.getElementById("button"+i);

    }

</script>


eval() 을 쓰지 않고 접근하는 방법이다. 



window객체를 재정의 하는법


만약에 


<script>

    console.log(test+ ":"+window.hasOwnProperty("test"));

    var test = "testing";

</script>


이런식으로 코드가 있다면 콘솔에는 undefined : true가 찍힌다. 글로벌 객체인 window는 이미 var 키워드로 정의한 변수를 가지고 있다는 것이다.. var 키워드로 정의한 변수는 최소 소스의 파싱 단계에서 미리 글로벌 변수로 정의되어 undefined가 박히게 된다.



<script>

    console.log(test+ ":"+window.hasOwnProperty("test"));

    test = "testing";

</script>


자 이렇게 var를 쓰지 않는다면 어떻게 될까?

false가 나온다 var 키워드를 사용하지 않으면 해당 구문이 직접 실행되는 순간에 글로벌 변수를 window객체의 속성으로 추가한다.




효율적인 변수 선언법


<script>

    function testFunc(flag) {

        if(flag) {

            var var1, var2, var3, var4;

            // ....

        } else {

            var var5;

            // ....

        }

    }

</script>



이 코드르 보자. if문 분기를 나누어서 여러 변수가 정의되어 있다. 두 번째 분기에는 변수르 조금 사용하기 때문에 얼핏 보기에는 메모리나 성능을 효율적으로 사용할 수 있다고 생각할 수 있다. 하지만 그렇지 않다. var 키워드로 정의하는 변수의 위치는 전혀 의미가 없다는 것을 알면 그렇다. var로 정의하면 해당 스코프의 실행환경에 진입하면서 미리 모든 변수를 찾아서 정의하고 값을 undefined로 박기때문에 분기를 나눈다고해서 달라질것이 전혀 없다.



"변수는 함수가 처음 시작할 때 하나의 var 키워드로 전부 묶어서 정의하라"


<script>

    function testFunc(flag) {

        var var1, var2, var3, var4, var5;

        if(flag) {

           

            // ....

        } else {


            // ....

        }

    }

</script>



이런식으로 정의한다. 이것이 성능에 영향을 미치지는 않지만 이렇게 하라는 이유는 컴퓨터의 문제가 아니라 사람에 문제가 있기 때문이다. 사람이 일으킬수있는 에러를 최소화하기위한 코딩 기법이다.


1. 초기화 실수의 최소화


2. 해당 스코프에서 사용하고 있는 변수에 대한 관리 용이


3. 미니피케이션 최적화


변수를 시작할 때 null이나 0으로 초기화한다. 그렇다면 검증할 때 확실하게 구분할 수 있다. 

선언을 하지않거나 초기화를 하지 않거나 typeof undefined검증을 하면 똑같이 나와서 다시 찾아보아야 한다. 하지만 null로 초기화해주면 [변수명] === null 로 명확하게 검증을 할 수 있다.


그리고 스코프가 실행되자마자 변수들을 모두 초기화하는 이점도 있다. 그리고 해당 스코프에서 사용하고 있는 변수에 대한 관리가 용이하다는 점인데 어떤 변수를 선언했는지 코드가 길어지거나 파일이 많아지게되면 찾기 힘들다. 


일반적으로 2중for문에서 var i=0 의 var를 빼먹게 된다면 안쪽 포문에서 i는 상위 스코프의 i를 참조하게되어 무한루프에 빠지는 경우가 만들어지게 된다. 만약 상단에 변수를 몰아서 선언했다면 쉽게 내부 함수에 있는 i가 var 키워드로 정의되어 있지 않아서 문제가 생긴다는 것을 알 수 있다.


이렇게 잠재적인 위험성을 방지하려할 때 변수를 모으면 좋은 것이다. 그리고 상단에 나열된 변수명과 초깃값들만 봐도 해당 스코프에서 어떤 작업을 하고자 하는지 판단할 수 있다. 


간단한 소스를 짤 때는 비효율적일지모르나 이러한 습관이 매우 중요하다. 3번 이점에서나오는 최적화에서 이유를 찾아보자. 이것은 min파일 즉 코드를 쭉 압축해놓은 파일을 본적이 있을 것이다. 즉 웹서버에서 내려받아야 할 소스의 크기를 최소화함으로써 웹서버의 가장 큰 병목중 하나인 다운속도를 최적화 할 수 있다.


그렇다면 매번 var를 선언하는 것보다 한번에 var 키워드하나에 쉼표를 찍어가며 변수를 선언했다면 바이트수가 줄게 된다. 큰 프로젝트의 자바스크립트 소스에서 생각해보면 매우 큰 차이인 것이다. 











반응형