지역변수를 지양하고 변수의 스코프를 줄일 수 있는 몇가지 방법을 살펴보자
모든 코드를 즉시 실행 함수로 감싸면 모든 변수는 즉시 실행 함수의 지역 변수가 된다.
(function(){
var foo = 10; //즉시 실행함수의 지역 변수
//..
}());
console.log(foo) // ReferenceError
전역에 네임스페이스 역할을 담당할 객체를 생성하고 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가하는 방법이다.
var MYAPP = {} // 전역 네임스페이스 객체
MYAPP.name = 'Lee';
MYAPP.age = 10;
console.log(MYAPP.name); // Lee
console.log(MYAPP.age); // 10
네임스페이스 객체에 또 다른 네임스페이스 객체를 프로퍼티로 추가해서 네임스페이스를 계층적으로 구성할 수도 있다.
var MYAPP = {}; // 전역 네임스페이스 객체
MYAPP.person = {
name: 'Lee',
address: 'Seoul'
};
console.log(MYAPP.person.name) // Lee
관련이 있는 변수와 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈을 만드는 것!
강력한 기능인 클로저를 기반으로 동작한다.
모듈 패턴의 특징은 전역 변수의 억제는 물론 캡슐화까지 구현 할 수 있다는 것이다.
자바스크립트 모듈 패턴의 사용예제
외부에 노출하고 싶은 변수나 함수를 담아 반환하고, 노출되소 싶지 않은 변수나 함수는 반환하는 객체에 추가하지 않는다.
const Counter = (function(){
const privateNum = 0; // 이 영역은 private
const publicNum = 0;
return{ // public 영역
publicNum,
increase(){
return ++num;
},
decrease(){
return --num;
}
};
}());
console.log(Counter.privateNum) // undefined
console.log(Counter.publicNum) // 0
console.log(Counter.increase()); //1
console.log(Counter.increase()); //2
console.log(Counter.decrease()); //1
대부분의 객체지향 프로그래밍 언어(자바같은 언어)는 클래스를 구성하는 멤버에 대하여, public, private, protected 등의 접근 제한자를 사용해 공개 범위를 한정할 수 있습니다.
자바스크립트는 public, private, protected 같은 접근 제한자를 제공하지 않는다.
하지만 최근 ES2019에 접근제한자 관련된 문법이 추가되었다.
class User {
#firstName;
#lastName;
#age;
constructor(firstName, lastName, age) {
this.#firstName = firstName;
this.#lastName = lastName;
this.#age = age;
}
get getAge() {
return this.#age;
}
set setAge(value) {
if (value < 0) {
throw Error('age can not be negative');
}
this.#age = value < 0 ? 0 : value;
}
}
const user1 = new User('Steve', 'Job', -1);
console.log(user1.#age); // # 프리픽스를 이용하여 은닉 상태가 되었기 때문에 직접 접근 불가능
console.log(user1.getAge); // -1
console.log(user1.setAge = 10); //10
console.log(user1.setAge = -1); // Uncaught Error: age can not be negative
이외에도 타입스크립트를 사용하면 자바와같은 객체지향프로그래밍 언어와 같이 private, public, protected 접근제한자를 사용 할 수 있다.
class Animal {
public name: string;
public constructor(theName: string) {
this.name = theName;
}
public move(distanceInMeters: number) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Animal {
private name: string;
constructor(theName: string) {
this.name = theName;
}
}
new Animal("Cat").name;
Property 'name' is private and only accessible within class 'Animal'.
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}
let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
// Hello, my name is Howard and I work in Sales.
console.log(howard.name);
// Property 'name' is protected and only accessible within class 'Person' and its subclasses.
ES6 모듈을 사용할 경우 파일 자체의 독자적인 모듈 스코프를 제공하기 때문에 전역변수를 사용할 필요가 없게 된다.
사용법은 간단하다 script 태그에 type="module" 어트리뷰트를 추가하면 로드된 자바스크립트 파일은 모듈로서 동작한다.
모듈의 파일 확장자는 mjs를 권장한다.
<script type="module" src="lib.mjs" ></script>
<script type="module" src="app.mjs" ></script>
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes/Private_class_fields
모던 자바스크립트 딥 다이브
typescript handbook