[js] 전역 변수의 사용을 억제하는 방법 - 즉시 실행 함수, ES6모듈
딥다이브 14장 전역변수의 문제점
전역 변수의 사용을 억제하는 방법
- 즉시 실행 함수
var counter = (function () {
var num = 0;
return {
increaseNum() {
return ++num;
},
decreaseNum() {
return --num;
},
getNum() {
return num;
},
setNum(newNum) {
num = newNum;
console.log(num);
}
};
}());
여기서 counter.num을 출력하면 무엇이나올까요?
만약 counter.num에 값을 할당하면 어떻게 될까요?
counter의 num에 300이 할당된것처럼 보입니다.
그렇다면 num은 private member가 아닌걸까요?
위에 작성한 동일한 즉시실행함수의 반환 객체를 또 다른 변수에 할당하겠습니다.
그리고 그 변수를 출력해보겠습니다.
num은 private member이기 때문에 아예 존재하지 않습니다.
그렇다면 이 상태에서 anotherCounter를 출력하면 num의 값을 조회할 수 있을까요?
이렇게 public member의 num이 생성된것을 확인할 수 있습니다. 이전에 private member인 num과는 전혀 다른것입니다.
- ES6
비슷한 구조를 즉시 실행 함수를 이용하여 구현할 수 있는데 ES5까지는 ES6모듈의 지원이 없었지만 ES6이후 ES6모듈로 간편하게 캡슐화를 할 수 있습니다.
index.html
<!doctype html>
<script type="module">
import { sayHello } from './greeting.js';
document.body.innerHTML = sayHello('hongjung');
</script>
greeting.js
export function sayHello(user) {
return `Hello, ${user}!`;
}
type="module"을 제거하면 다음과 같은 오류가 납니다.
웹브라우저가 자바스크립트 파일이 모듈이 아니라고 인식하기 때문입니다.
모듈 이름 재정의
수 많은 모듈이 있다면 중복된 이름이 있을 수 밖에 없을 것입니다.
이런 경우 어떻게 해야할까요?
import { sayHello as hi } from './greeting.js';
다음과 같이 재정의 해주면 그대로 출력됩니다.
ES6모듈은 재정의를 해줘야해서 즉시 실행 함수와 차이가 있다고 생각하였으나 즉시 실행 함수도 그것을 할당한 변수가 충돌하지 않게 다른 이름으로 하는것처럼 그러한 차이는 없는것이라고 생각합니다. 다만, 스크립트 단위로 관리할 수 있는점에서 ES6모듈이 더 편리한것이라고 생각합니다.
참고자료
- 책 '모던 자바스크립트 deep dive'
- 모듈의 이해