모던 자바 스크립트 DeepDive(11)

samuel Jo·2022년 8월 3일
0

딥다이브

목록 보기
11/34

Chapter 14

전역변수의 문제점

무분별한 전역 변수 사용은 위험함. 전역 변수를 반드시 사용해야할 이유가 없다면 지역변수 사용.

변수의 생명주기

1. 지역변수의 생명 주기

변수는 선언에 의해 생성되고 할당을 통해 값을 갖고 , 언젠간 소멸. 변수가 생성된 후에 소멸하지 않는다면 프로그램을 종료하지않는한 계속 메모리 공간을 점유함.

예시로 알아보자.

function foo() {
  var x = 'local';
  console.log(x); // local
  return x;
}
foo();
console.log(x); // ReferenceError: x is not defined

foo()함수 안에 선언된 지역변수 x는 함수안에서만 살아 있다고 보면된다. 그래서 밖에서 x를 찍으면 에러가 발생.({}중괄호 사이에서 살아있음.)

var x = 'global';

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

위코드에서 foo()함수 내부에서 선언된 지역변수x는 ①시점에서 이미 선언 되었고 undefined(함수호이스팅? var x;) 전역변수 x를 참조하는것이 아니라 지역변수 x를 참조해 값을 출력.

호이스팅은 스코프를 단위로 동작.

지역변수는 함수전체에서 유효. 호이스팅은 변수 선언이 스코프의 선두로 글어 올려진 것처럼 동작하는 자바스크립트 고유의 특징.

전역변수의 생멍주기

전역코드 : 함수와 달리 명시적 호출없이 실행
실행되는 특별한 진입점이 없음
반환문 사용 x
더이상 실행할 문이 없을때 종료
전역객체
전역변수의 생명주기와 같음. 코드가 실행되기 이전단계에 먼저 생성되는 특수한 객체
프로퍼티로 갖는 것들
표준 빌트인 객체 -> Object, String, Number, Function, Array 등등
호스트객체 -> 클라이언트 Web, 각종 API
var 키워드로 선언한 전역 변수, 전역 함수
var 키워드로 선언한 전역변수는 전역객체 window의 프로퍼티
var 키워드로 선언한 전역변수의 생명주기는 전역객체의 생명주기와 일치 (var키워드의 단점)

전역변수의 문제점

1. 암묵적 결합

전역변수를 선언한 의도는 코드 어디서든 참조하고 할당하는 변수를 사용하겠단 의도. 전연변수를 참조하고 변경할수있는 암묵적 결합을 허용.

유효범위가 크면 클수록 코드의 가독성⬇

의도치않은 변경위험성도 ⬆

2. 긴 생명주기

전역 변수는 생명주기가 길다. 메모리 리소스도 오랜기간 소비. var키워드는 중복선언도 가능해서 이름이 중복될 가능성도 ⬆

var x = 1;

// 변수의 중복 선언. 기존 변수에 값을 재할당한다.
var x = 100;
console.log(x); // 100

3.스코프체인 사에서 종점에 존재

전역 변수는 스코프체인상에서 종점에 존재. => 변수를 검색할때 전역변수가 가장마지막에 검색된다는 것. 이는 전역변수의 검색 속도가 가장 느리다 볼 수 있다. 크진않지만 속도의 차이는 있다.

4. 네임스페이스 오염

파일이 분리되어 있어도 하나의 전역 스코프를 공유함

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

전역변수를 반드시 써야할 이유가 없으면 지역변수 사용. 스코프는 좁으면 좁을수록 좋다.

1. 즉시 실행 함수

  • 함수 정의와 동시에 호출됨 (단 한 번만 호출)
  • 모든 코드를 즉시 실행 함수로 감싸면 모든 변수는 즉시 실행 함수의 지역 변수가 됨
    (function () {
     var foo = 10; // 즉시 실행 함수의 지역 변수
     // ...
    }());
    console.log(foo); // ReferenceError: foo is not defined

2 네임스페이스 객체

  • 전역에 네임스페이스 역할 담당할 객체 생성하고 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가
  • 네임스페이스 객체에 또 다른 네임스페이스 객체를 프로퍼티로 추가해서 계층적으로 구성도 가능
var MYAPP = {}; // 전역 네임스페이스 객체
MYAPP.name = 'Lee';
console.log(MYAPP.name); // Lee

3. 모듈 패턴

  • 클래스를 모방해 관련 있는 변수와 함수 모아 즉시 실행 함수로 감싸 하나의 모듈로 구성
    • 클로저 기반으로 동작 -> 전역 변수 억제
    • 전역 변수 억제, 캡슐화 효과
    • 전역 네임스페이스의 오염 막기, 정보 은닉 구현 위해 사용
    • 캡슐화: 객체의 state를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작하는 behavior인 메서드를 하나로 묶음
  • 캡슐화는 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용하기도 함 (information hiding)
    • JS는 access modifier (접근 제한자) 기능 제공 X (TS는 제공)
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

4. ES6모듈

- 파일 자체의 독자적인 모듈 스코프 제공
- script 태그에 type="module" 속성 (attribute)를 추가하면 로드된 js 파일은 모듈로서 동작함
- 모듈의 파일 확장자는 mjs를 권장
- Webpack의 모듈 번들러 사용하는 것이 일반적임
profile
step by step

0개의 댓글