티스토리 뷰

728x90
반응형

전역 변수 최소화-javascript pattern 참고 및 정리

모든 자바스크립트 실행 환경에는 전역 객체가 존재한다.
어떤 함수에도 속하지 않는 상태에서 this를 사용하면 전역 객체에 접근하게 된다.
전역 변수를 생성하는 것은 , 이 전역 객체의 프로퍼티를 만드는 것과 같다.
편의상 브라우저에는 전역객체에 window라는 부가적인 프로퍼티가 존재하며 전역 객체자신을 가리킨다.

myglobal="hello";//안티패턴
console.log( myglobal );//"hello"
console.log( window.myglobal )// "hello"
console.log( window["myglobal"] ) //"hello"
console.log( this.myglobal )// hello

전역변수의 문제점은 자바스크립트 애플리케이션이나 웹페이지 내 모든 코드 사이에서 공유된다는 점이다.
즉 모든 전역 변수는 동일한 전역 네임스페이스 안에 존재하기 때문에 애플리케이션 내의 다른 영역에서 
목적이 다른 전역 변수를 동일한 이름으로 정의할 경우 서로 덮어쓰게 된다.
자바스크립트의 성격상, 의도하지 않았더라도 전역 변수를 만들기가 너무나 쉽다.

1. 자바스크립트에서는 변수를 선언하지 않고도 사용할 수 있다.
2. 자바스크립트에는 암묵적 전역이라는 개념이 있다.

즉 var 선언하지 않고 사용한 변수는 자동으로 전역 객체의 프로퍼티가 되어 명시적으로 
선언된 전역 변수와 별 차이 없이 사용할 수 있다.


//암묵적 전역 생성하는 안티패턴
function sum( x, y ){
    //안티패턴: 암묵적 전역
    result=x+y;
    return result;
}
잘 동작하지만 이 함수를 호출하고 나면 전역 네임스페이스에 result라는 변수가 남아 문제를 일으킬 수도 잇다.
sum()함수를 개선하면 다음과 같다.
function sum( x, y ){
   var result=x+y;
   return result;
}

//암묵적 전역 생성하는 안티패턴 var 선언에 있어서 연쇄적 할당
function foo(){
     var a=b=0;
}




var 선언을 빼먹었을 때의 부작용
암묵적 전역 변수와 명시적으로 선언된 변수 사이에 존재하는 또 하나의 작은 차이점은 
delete 연산자를 사용하여 이 변수의 정의를 취소할 수 있는지 여부다.

var를 사용하여 명시적 선언된 전역변수는 삭제 못함. ( 프로그램내에 선언되었지만 함수에 속하지 않은 변수 )
var를 사용하지 않고 생성한 암묵적 전역 변수는 삭제 가능.( 함수안이든 밖이든 상관없이 )

이는 암묵적 전역 변수가 엄ㅣㄹ히 말하면 변수가 아니라 전역 객체의 프로퍼티라는 사실을 보여준다.
프로퍼티는  delete 연산자로 삭제가능 하지만 변수는 그렇지 않다.


var global_var=1;
global_novar=2;
(function(){
  global_fromfunc=3;
}() );

delete global_var;
delete global_novar;
delete global_fromfunc;

console.log( typeof global_var );
console.log( typeof global_novar ); 
console.log( typeof global_fromfunc );



단일 var 패턴
함수 상단에서 var선언을 한 번만 쓰는 패턴을 유용하고 시도해 볼 만하다.
다음과 같은 이점이 있다.
1. 함수에서 필요로 하는 모든 지역 변수를 한군데서 찾을 수 있다.
2. 변수를 선언하기 전에 사용할 때 발생하는 로직상의 오류를 막아준다.
3. 변수를 먼저 선언한 후에 사용해야 한다는 사실을 상기시키기 때문에 전역 변수를 최소화하는 데 도움이 된다.
4. 코드량이 줄어든다. ( 작성량과 전송량 모두 줄어든다 )
function func(){
     var a=1,
     b=2,
     sum=a+b,
     myobject={},
     i,
     j;
     //함수 본문....
}
문법오류를 막고 (초기값없이 선언된 변수들은 모두 undefined라는 값으로 초기화된다)
코드 가독성도 향상된다. 
나중에 코드를 볼 때, 변수의 초기 값에 근거해 변수의 용도가 무엇인지, 즉 객체를 할당할 
변수였는지 정수를 할당할 변수였는지 짐작할 수 있다.

실질적인 작업을 일부 해둘 수도 있다.
DOM 참조를 다루는 것도 좋은 예다.

function updateElement(){
    var el=document.getElementById("result"),
    style=el.style;
    //el과 style을 다루는 코드.....
}



호이스팅(hoistion):분산된 var 선언의 문제점
javascript 에서는 함수 내 여기저기서 여러 개의 var선언을 사용할 수 있지만,
실제로는 모두 함수 상단에서 변수가 선언된 것과 동일하게 동작한다. 이러한 동작 방식을 호이스팅(끌어올리기)이라고 한다.
때문에 함수 안에서 변수를 사용한 다음에 선언하면 로직상의 오류를 일으킬 수 있다.
javascript는 동일한 유효범위( 동일한 함수 )안에 있는 변수는 var선언 전에 사용해도 이미 선언된 것으로 간주한다.
myname="global";//전역변수
function func(){
   console.log(myname); //"undefined"
   var myname="local";
   console.log(myname); //"local"
}
func();
첫번째 console.log결과로 "global"이 출력되고 두 번째에는 "local"이 출력될 거라고 예상하기 쉽다.
첫번째 호출되는 시점에는 myname이 아직 선언되지 않았으므로 전역 변수인 myname을 바라볼 것이라고 예상해야 맞을 것 같다.  
그러나 실제 동작을 그렇지 않다. 첫번째 console.log은 'undefined'를 출력한다.
myname이 이 함수의 지역 변수로 선언되었다고 간주하기 때문이다.
모든 변수 선언문은 함수 상단으로 끌어올려진다.  사용할 변수를 모두 맨 첫 줄에서 선언하는 것이 좋다.
myname="global";//전역 변수
function func(){
    var myname; //이렇게 쓴 것과 동일하다.-> var myname=undefined;
    console.log(myname); //"undefined"
    myname="local";
    console.log(myname);//"local"
}
func();


728x90
반응형
댓글