자바스크립트 전역 변수의 문제점

csb·2021년 1월 13일
0

자바스크립트

목록 보기
2/7

전역 변수의 무분별한 사용은 위험하다.
전역 변수를 반드시 사용해야 할 이유를 찾지 못한다면 지역 변수를 사용해야 한다.

변수의 생명주기

지역 변수의 생명주기

function foo() {
	var x = 'local';
    console.log(x); // local
    return x;
}

foo();
console.log(x); // ReferenceError: x is not defined

지역 변수 x는 foo 함수가 호출되기 이전까지는 생성되지 않는다.
foo 함수를 호출하지 않으면 함수 내부의 변수 선언문이 실행되지 않기 때문이다.
foo 함수를 호출하면 함수 몸체의 다른 문들이 순차적으로 실행되기 이전에 x 변수의 선언문이 자바스크립트 엔진에 의해 가장 먼저 실행되어 x 변수가 선언되고 undefined로 초기화된다.
그 후, 함수 몸체를 구성하는 문들이 순차적으로 실행되기 시작하고 변수 할당문이 실행되면 x변수에 값이 할당된다.
그리고 함수가 종료하면 x변수도 소멸되어 생명 주기가 종료된다.
따라서 함수 내부에서 선언된 지역 변수 x는 foo 함수가 호출되어 실행되는 동안에만 유효하다.
즉, 지역 변수의 생명 주기는 함수의 생명 주기와 일치한다.

var x = 'global';

function foo() {
	console.log(x); // 1
    var x = 'local';
}

foo();
console.log(x); // global

위 예제의 실행 결과를 예측해보라
.
.
.
.
.
.
.
.
.
.
.
.
.
foo 함수 내부에서 선언된 지역 변수 x는 1의 시점에 이미 선언되었고 undefined로 초기화되어 있다.
따라서 전역 변수 x를 참조하는 것이 아니라 지역 변수 x를 참조해 값을 출력한다.
즉, 지역 변수는 함수 전체에서 유효하다.
단, 변수 할당문이 실행되기 이전까지는 undefined값을 갖는다.

전역 변수의 생명 주기

브라우저 환경에서 전역 객체는 window이므로 브라우저 환경에서 var 키워드로 선언한 전역 변수는 전역 객체 window의 프로퍼티다.
전역 객체 window는 웹페이지를 닫기 전까지 유효하다.
따라서 브라우저 환경에서 var 키워드로 선언한 전역 변수는 웹페이지를 닫을 때까지 유효하다.
즉, var 키워드로 선언한 전역 변수의 생명 주기는 전역 객체의 생명 주기와 일치한다.

전역 변수의 문제점

  1. 암묵적 결합
  2. 긴 생명 주기
  3. 스코프 체인 상에서 종점에 존재 - 전역 변수의 검색 속도가 가장 느리다
  4. 네임스페이스 오염 - 다른 파일 내에서 동일한 이름으로 명명된 변수나 전역 함수가 같은 스코프 내에 존재할 경우 예상치 못한 결과를 가져올 수 있다.

전역 변수의 사용을 억제하는 방법

변수의 스코프는 좁을수록 좋다

즉시 실행 함수 (IIFE)

모든 코드를 즉시 실행 함수로 감싸면 모든 변수는 즉시 실행 함수의 지역 변수가 된다.

(function () {
	var foo = 10; // 즉시 실행 함수의 지역 변수
    // ...
}());

console.log(foo); // ReferenceError: foo is not defined

네임스페이스 객체

전역에 네임스페이스 역할을 담당할 객체를 생성하고 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가하는 방법이다.

var MYAPP = {}; // 전역 네임스페이스 객체

MYAPP.name = 'Lee';

console.log(MYAPP.name); // Lee
var MYAPP = {}; // 전역 네임스페이스 객체

MYAPP.person = {
	name: 'Lee',
    address: 'Seoul'
};

console.log(MYAPP.person.name); // Lee

모듈 패턴

var Counter = (function() {
	// private 변수
    var num = 0;
    
    // 외부로 공개할 데이터나 메서드를 프로퍼티로 추가한 객체를 반환한다.
    return {
    	increase() {
        	return ++num;
        },
        decrease() {
        	return --num;
        }
    };
}());

// private 변수는 외부로 노출되지 않는다.
console.log(Counter.num); // undefined

console.log(Counter.increase()); // 1
console.log(Counter.increase()); // 2
console.log(Counter.decrease()); // 1
console.log(Counter.decrease()); // 0

ES6 모듈

ES6 모듈은 파일 자체의 독자적인 모듈 스코프를 제공한다.
모던 브라우저에서는 ES6 모듈을 사용할 수 있다.
script 태그에 type='module' 어트리뷰트를 추가하면 로드된 자바스크립트 파일은 모듈로서 동작한다.
모듈의 파일 확장자는 mjs를 권장한다.

<script type="module" src="lib.mjs"></script>
<script type="module" src="app.mjs"></script>

참고

0개의 댓글