221013 TIL | 자바스크립트 코딩 기법과 핵심 패턴_#5 객체 생성 패턴

네임스페이스 패턴

  • 프로그램에서 필요로 하는 전역 변수의 개수를 줄이는 동시에, 접두어를 사용하지 않고도 이름이 겹치지 않게 해준다.
  • 자바스크립트에 네임스페이스라는 함수는 없지만, 별도로 구현할 수 있다.
// 네임스페이스 함수를 사용한다.
MYAPP.namespace('MYAPP.modules.module2');

// 결과 반환
var MYAPP = {
	module: {
		module2: {}
	}
};

  • namespace() 를 구현한 예제
    • namespace는 자바스크립트의 예약어이다. 쓰지 않는 것을 권한다.
var MYAPP = MYAPP || {};

MYAPP.namespace = function (ns_string) { 
	var parts = ns_string.split('.'),
	parent = MYAPP, i;
	// 처음에 중복되는 전역 객체명은 제거한다
	if (parts[0] === "MYAPP") { 
		parts = parts.slice(l);
	}
	for (i = 0; i < parts.length; i += 1) {
		// 프로퍼티가 존재하지 않으면 생성한다.
		if (typeof parent[parts[i]] === "undefined") { 
			parent[parts[i]] = {};
		}
		parent = parent[parts[i]];
	}
	return parent;
};

의존 관계 선언

  • 자바스크립트 라이브러리들은 대개 네임스페이스를 지정하여 모듈화 되어 있다.
  • 이 때 함수나 모듈 내 최상단에 의존 관계에 있는 모듈을 선언하는 것이 좋다.
// YUI 라이브러리 예시
// YAHOO.util.Event, YAHOO.util.Dom 같은 모듈이 추가되어 있다고 할 때
var myFunction = function() {
	// 의존 관계에 있는 모듈들을 지역변수로 선언하고,
	var event = YAHOO.util.Event,
			dom = YAHOO.util.Dom;
	// 이제 event와 dom이라는 변수를 사용한다.
};

의존 관계 선언 시 장점

  • 명시적으로 선언되어 있어 코드를 사용하는 사람이 페이지 내에 포함시켜야 하는 스크립트 파일이 무엇인지 알 수 있다.
  • 지역 변수(dom)은 전역 변수(YAHOO.util.Dom)보다 호출이 빠르다. (전역 객체 판별을 단 한번만 수행하기 때문.)

비공개 프로퍼티와 메서드

  • 자바스크립트는 private, protected, public 접근 제한자가 없지만
  • 클로저를 사용해서 private를 구현할 수 있다.

모듈 패턴

  • 자바스크립트에 별도로 모듈 패턴이라는 패턴이 있는 것이 아니라, 다음 패턴 여러 개를 조합한 것이다.
    • 네임스페이스 패턴
    • 즉시 실행 함수
    • 비공개 멤버와 특권 멤버
    • 의존 관계 선언
      1. 네임스페이스를 설정
MYAPP.namespace('MYAPP.utilities.array'); 
  1. 모듈 정의
MYAPP.utilities.array = (function () { 
	return {
	// 여기에 객체 내용을 구현한다...
	}; 
}());
  1. 공개 인터페이스에 메서드 추가
MYAPP.utilities.array = (function () { 
	return {
		inArray: function (needle, haystack) { 
			// ...
	},
	isArray: function (a) {
		// ... }
	}; 
}());

즉시 실행 함수가 반환하는 최종 결과는 모듈의 공개 API를 담은 객체이다.

MYAPP.namespace('MYAPP.utilities.array'); 
MYAPP.utilities.array = (function () {
	// 의존관계
	var uobj = MYAPP.utilities.object, 
			ulang = MYAPP.utilities.lang,

			// 비공개 프로퍼티
			array_string = "[object Array]", ops = Object.prototype.toString;
		// 비공개 메서드들 
		// ...

		// var 선언을 마친다.
		
		// 필요하면 일회성 초기화 절차를 실행한다.
		// ...

		// 공개 API
		return {

			inArray: function (needle, haystack) {
				for (var i = 0, max = haystack.length; i < max; i += 1) {
					if (haystack[i] === needle) { 
						return true;
					}
				}
			},

			isArray: function (a) {
				return ops.call(a) === array_string;
			}
			// ... 더 필요한 메서드와 프로퍼티를 여기 추가한다. 
	};
}());