[JS Basic] 전역변수 vs 지역변수

재오·2022년 10월 4일
2

JavaScript

목록 보기
11/48
post-thumbnail

변수는 자신이 선언된 위치에서 생성되고 소멸한다. 전역 변수의 생명 주기는 애플리케이션의 생명 주기와 같다. 하지만 함수 내부에서 선언된 지역 변수는 함수가 호출되면 생성되고 함수가 종료하면 소멸한다.

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

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

즉 지역 변수의 생명 주기는 함수의 생명 주기와 일치한다.

다음 예제를 살펴보자.

var x = 'global';

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

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

foo() 함수 내부에서 x의 출력값이 왜 undefined가 될까? 이는 호이스팅과 관련이 있는 것이 분명해 보인다. 이 정도면 정말 호이스팅을 자바스크립트 내부에서 가장 중요한 기능이라고 할 수 있을 것으로 보인다. 호이스팅은 스코프를 단위로 동작한다.

지역변수의 호이스팅은 선언이 되어 있다면 undefined 가 먼저 할당된다. 지역변수와 비슷한 성격을 가진다. 바로 다음줄에 local 이 선언, 할당이 되어있기 때문에 변수 호이스팅이 발생하는 것이다.

var x -> undefined -> local(오류는 발생하지 않는다)

전역변수의 문제점

암묵적 결합

  • 전역변수를 사용하겠다는 것은 코드 어디에서든 변수를 참조하고 사용하겠다는 것이다. 이는 즉 모든 코드가 전역 변수를 참조하고 변경할 수 있는 암묵적 결합을 허용한다는 것이다.

긴 생명 주기

  • 전역 변수는 생명 주기가 길기 때문에 메모리 리소스도 오랜 기간 소비한다.
  • var 키워드는 변수의 중복 선언이 가능하기 때문에 의도치 않은 재할당이 이루어질 수도 있다.

스코프체인에서의 문제

  • 앞에 스코프 체인에서도 배웠듯 지역변수를 먼저 검색하고 최종적으로 전역 변수를 검색한다. 이는 전역 변수의 검색 속도가 가장 느리다는 의미로 해석이 된다.

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

즉시 실행 함수

  • 모든 코드를 즉시 실행함수로 감싸면 모든 변수는 즉시 실행함수의 지역 변수가 되고 한번만 실행되기 때문에 효율이 좋다.
(function () {
	var foo = 10;
    // ...
} ());

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

네임스페이스 객체

  • 전역에 네임스페이스 역할을 담당할 객체를 생성하고 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가하는 방법이다. 계층적으로도 구성이 가능하다.
var MYAPP = {};

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

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

모듈 패턴

캡슐화는 객체의 상태를 나타내는 프로퍼티와 매서드를 하나로 묶는 것을 의미한다.
객체의 특정 프로퍼티나 매서드를 감출 목적으로 사용하기도 하는데 이를 정보 은닉이라고 한다.

자바스크립트는 C처럼 클래스 public, private등 접근 제한자를 제공하지 않는다. 모듈패턴은 정보 은닉을 구현하기 위해 사용한다.

public 처럼 사용하고 싶으면 return 객체로 묶어주면 된다.

var Counter = (function () {
    var num = 0; // private 역할...외부에서 선언이 불가능하다

    return {
        increase() {
            return ++num; // public 역할
        },
        decrease() {
            return --num; //public 역할
        }
    };
}());

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
profile
블로그 이전했습니다

0개의 댓글