모듈 식 프로그래밍은 매우 일반적인 JavaScript 프로그래밍 패턴입니다. 일반적으로 코드를 이해하기 쉽게 만들 수 있지만 잘 알려지지 않은 많은 우수한 관행이 있습니다.
베이스
Eric Miraglia (Yui의 개발자)가 3 년 전에 모듈 식 패턴을 설명하는 블로그를 처음 게시 한 이후 먼저 몇 가지 모듈 식 패턴을 간략하게 설명하겠습니다. 이러한 모듈 식 모드에 이미 친숙하다면이 섹션을 직접 건너 뛰고 "고급 모드"에서 읽기 시작할 수 있습니다.
익명 폐쇄
이것은 모든 것을 가능하게하는 기본 구조이며 JavaScript의 가장 좋은 기능이기도합니다. 우리는 단순히 익명의 기능을 만들고 즉시 실행합니다. 모든 코드는이 기능 내에서 실행되며 민영화를 제공하는 클로저에서 실시되며, 이는 이러한 클로저의 변수가 응용 프로그램의 전체 수명을 통과 할 수 있도록 충분합니다.
코드 사본은 다음과 같습니다.
(기능 () {
// ... 모든 vars와 함수는이 범위에만 있습니다.
// 여전히 모든 글로벌에 대한 액세스를 유지합니다
} ());
익명 함수를 감싸는이 쌍의 가장 바깥 쪽 괄호에 주목하십시오. JavaScript의 언어 특성으로 인해 괄호에 필요합니다. JS의 키워드 기능으로 시작하는 진술은 항상 함수 선언으로 간주됩니다. 이 코드를 괄호 안에 랩핑하여 통역사에게 기능 표현식임을 알리십시오.
글로벌 변수 가져 오기
JavaScript에는 암시 적 글로벌 변수라는 기능이 있습니다. 변수 이름이 어디에 있든 상관없이 통역사는 범위 체인에 따라 변수의 VAR 선언문을 리버스로 찾을 수 있습니다. VAR 선언문을 찾을 수없는 경우이 변수는 글로벌 변수로 간주됩니다. 이 변수가 할당 문에 사용되고 변수가 존재하지 않으면 전역 변수가 생성됩니다. 이는 익명 폐쇄에서 사용하거나 글로벌 변수를 쉽게 만들 수 있음을 의미합니다. 불행히도, 이것은 사람들의 직관적 인 감정의 경우, 그 변수가 글로벌이라는 것을 한눈에 알리는 것은 불가능하기 때문에 유지하기가 매우 어렵습니다.
다행히도 우리의 익명 기능은 간단한 해결 방법을 제공합니다. 글로벌 변수를 매개 변수로 익명 함수로 전달하면 암시 적 글로벌 변수보다 명확하고 빠른 코드를 얻을 수 있습니다. 예는 다음과 같습니다.
코드 사본은 다음과 같습니다.
(기능 ($, yahoo) {
// 이제이 코드에서 Globals jQuery ($) 및 Yahoo에 액세스 할 수 있습니다.
} (jQuery, yahoo));
모듈 내보내기
때로는 글로벌 변수를 사용하기를 원할뿐만 아니라 반복적으로 사용하도록 선언하고 싶습니다. 익명 함수의 반환 값을 통해 파생을 통해 쉽게 할 수 있습니다. 이렇게하면 기본 모듈 식 모델이 완료되며 다음은 완전한 예입니다.
코드 사본은 다음과 같습니다.
var module = (function () {
var my = {},
privatevariable = 1;
함수 privatemethod () {
// ...
}
my.moduleproperty = 1;
my.modulemethod = function () {
// ...
};
내 반환;
} ());
모듈이라는 2 가지 공개 속성이있는 모듈이라는 글로벌 모듈을 선언했습니다. Module.ModuleMethod라는 메소드 및 Module.ModuleProperty라는 변수입니다. 또한 익명 기능 폐쇄를 사용하는 개인 내장 상태를 유지합니다. 동시에 필요한 글로벌 변수를 쉽게 가져오고 이전에 배운 대로이 모듈 식 패턴을 사용할 수 있습니다.
고급 모드
위 섹션에 설명 된 기초는 많은 상황을 다루기에 충분하며 이제는이 모듈 식 모델을 더욱 개발하여보다 강력하고 확장 가능한 구조를 만들 수 있습니다. 모듈 모듈부터 시작하여 이러한 고급 모드를 하나씩 소개하겠습니다.
줌 모드
전체 모듈은 한 파일의 모듈 식 모드 제한이어야합니다. 대규모 프로젝트에 관여하는 사람은 누구나 JS로 여러 파일을 분할하는 가치를 이해합니다. 다행히도 모듈을 증폭시키기위한 훌륭한 구현이 있습니다. 먼저 모듈을 가져 와서 속성을 추가 한 후 마지막으로 내보내십시오. 예는 다음과 같습니다. 원래 모듈에서 확대합니다.
코드 사본은 다음과 같습니다.
var module = (function (my) {
my.anothermethod = function () {
// 추가 방법 ...
};
내 반환;
}(기준 치수));
VAR 키워드를 사용하여 일관성을 보장하지만 여기서는 필요하지 않습니다. 이 코드가 실행 된 후, 당사의 모듈에는 이미 모듈이라는 새로운 공개 메소드가 있습니다. 이 확대 파일은 또한 자체 개인 내장 상태 및 가져온 객체를 유지 관리합니다.
넓은 줌 모드
위의 예제는 초기화 모듈을 먼저 실행 한 다음 증폭 된 모듈을 실행해야하며, 때로는 반드시 필요한 것은 아닙니다. JavaScript 응용 프로그램이 성능을 향상시키기 위해 수행 할 수있는 가장 좋은 방법 중 하나는 스크립트를 비동기 적으로 실행하는 것입니다. 유연한 멀티 파트 모듈을 생성하고 넓은 줌 모드를 통해 모든 순서로로드 할 수 있습니다. 각 파일은 다음 구조로 구성해야합니다.
코드 사본은 다음과 같습니다.
var module = (function (my) {
// 기능 추가 ...
내 반환;
} (모듈 || {});
이 패턴에서 VAR 표현식은 필요합니다. 모듈이 초기화되지 않은 경우이 가져 오기 명령문은 모듈을 생성합니다. 즉, Labjs와 같은 도구를 사용하여 모든 모듈 파일을 차단하지 않고 병렬로로드 할 수 있습니다.
꽉 확대 모드
와이드 선거 모드는 매우 좋지만 모듈에 약간의 제한이 있습니다. 가장 중요한 것은 모듈의 속성을 안전하게 덮어 쓸 수 없습니다. 초기화시 다른 파일의 속성을 사용할 수는 없습니다 (그러나 실행할 때 사용할 수 있습니다). 단단한 확대 모드에는로드 된 시퀀스가 포함되어 있으며 속성을 재정의 할 수 있습니다. 다음은 간단한 예입니다 (원래 모듈의 확대) :
코드 사본은 다음과 같습니다.
var module = (function (my) {
var old_modulemethod = my.modulemethod;
my.modulemethod = function () {
// 메소드 오버라이드, old_modulemethod를 통해 이전에 액세스 할 수 있습니다 ...
};
내 반환;
}(기준 치수));
위의 예에서 모듈의 구현을 무시하지만 필요할 때 원래 방법에 대한 참조를 유지할 수 있습니다.
복제 및 상속
코드 사본은 다음과 같습니다.
var module_two = (function (old) {
var my = {},
열쇠;
(오래된 키) {
if (old.hasownproperty (key)) {
내 [key] = old [key];
}
}
var super_modulemethod = old.modulemethod;
my.modulemethod = function () {
// 클론에서 메소드 오버라이드 메소드, super_modulemethod를 통해 Super에 대한 액세스
};
내 반환;
}(기준 치수));
이 모델은 아마도 가장 유연하지 않은 옵션 일 것입니다. 코드를 깔끔하게 보이게하지만 유연성 비용이 발생합니다. 위에서 쓴 것처럼 속성이 객체 또는 함수 인 경우 복사되지는 않지만 객체 또는 기능에 대한 두 번째 참조가됩니다. 그중 하나를 수정하면 다른 하나를 동시에 수정합니다 (번역기 주 : 단순히 하나이기 때문에). 이것은 재귀 적 복제 과정에 의해 해결 될 수 있지만, 기능 클로닝은 해결되지 않을 수 있으며, 아마도 평가로 해결할 수 있습니다. 따라서이 기사 에서이 방법은 기사의 무결성을 고려하여 만 말합니다.
크로스 파일 개인 변수
모듈을 여러 파일로 분할하는 데 큰 제한이 있습니다. 각 파일은 자체 개인 변수를 유지하고 다른 파일의 경우 개인 변수에 액세스 할 수 없습니다. 그러나이 문제는 해결 될 수 있습니다. 다음은 파일에서 개인 변수를 유지하는 광범위한 모듈의 예입니다.
코드 사본은 다음과 같습니다.
var module = (function (my) {
var _private = my._private = my._private || {},
_seal = my._seal = my._seal || 기능 () {
my._private를 삭제합니다.
my._seal을 삭제합니다.
my._unseal;
},
_unseal = my._unseal = my._unseal || 기능 () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// _PRIVATE, _SEAL 및 _UNSEAL에 대한 영구 액세스
내 반환;
} (모듈 || {});
모든 파일은 해당 _Private 변수에서 속성을 설정할 수 있으며 다른 파일에서 액세스 할 수 있음을 이해합니다. 이 모듈이로드되면 응용 프로그램은 모듈을 호출 할 수 있습니다 ._seal ()은 내부 _private에 대한 외부 호출을 방지 할 수 있습니다. 이 모듈을 재구성 해야하는 경우 새 파일을로드하기 전에 모든 파일의 내부 메소드가 _unseal ()을 호출하고 새 파일을 실행 한 후 다시 _seal ()을 호출 할 수 있습니다. 나는 지금 직장 에서이 패턴을 사용하고 다른 곳에서는 보지 못했습니다. 나는 이것이 매우 유용한 모델이라고 생각 하며이 모델 자체에 대한 기사를 작성할 가치가 있습니다.
하위 모듈
우리의 마지막 고급 모드는 분명히 가장 쉬운 모드입니다. 서브 모듈을 만드는 훌륭한 예가 많이 있습니다. 일반 모듈을 만드는 것과 같습니다.
코드 사본은 다음과 같습니다.
module.sub = (function () {
var my = {};
// ...
내 반환;
} ());
이것은 단순 해 보이지만 여기서 언급 할 가치가 있다고 생각합니다. 서브 모듈은 증폭 모드 및 민영화 상태를 포함하여 일반 모듈의 모든 고급 장점을 가지고 있습니다.
결론적으로
대부분의 고급 모드를 결합하여보다 유용한 모드를 만들 수 있습니다. 복잡한 애플리케이션 설계를위한 모듈 식 패턴을 권장하려면 넓은 증폭 모드, 개인 변수 및 서브 모듈을 결합하도록 선택합니다.
나는 이러한 모드의 성능을 고려하지 않았지만, 이것을 간단한 사고 방식으로 바꾸고 싶습니다. 모듈 식 모드가 좋은 성능을 가지고 있다면,이 스크립트 파일을 더 빨리 다운로드 할 수있는 훌륭한 작업을 수행 할 수 있습니다. 넓은 확대 모드를 사용하면 간단한 비 블로킹 병렬 다운로드가 가능하여 다운로드 속도가 빨라집니다. 초기화 시간은 다른 방법보다 약간 느릴 수 있지만 장단점을 측정 한 후에는 가치가 있습니다. 글로벌 변수 가져 오기가 정확한 한, 런타임 성능에 영향을 미쳐야하며, 개인 변수로 참조 체인을 단축시켜 서브 모듈에서 더 빠른 달리기 속도를 달성 할 수 있습니다.
결론적으로, 여기에는 자식 모듈이 부모 모듈에 동적으로로드되는 예입니다 (부모 모듈이 존재하지 않으면 생성). 단순화를 위해 개인 변수를 제거했으며 개인 변수를 추가하는 것은 매우 간단합니다. 이 프로그래밍 패턴을 사용하면 전체 복잡한 계층 구조 코드베이스를 서브 모듈을 통해 병렬로로드 할 수 있습니다.
코드 사본은 다음과 같습니다.
var util = (기능 (부모, $) {
var my = parent.ajax = parent.ajax || {};
my.get = function (url, params, 콜백) {
// 좋아, 그래서 나는 조금 속임수를 쓰고있다 :)
return $ .getJson (url, params, 콜백);
};
// 등...
반환 부모;
} (util || {}, jQuery);
이 기사는 "JavaScript Modular Programming"의 현재 모범 사례를 요약하고 실습 방법을 설명합니다. 이것은 기본 튜토리얼이 아니지만 JavaScript의 기본 구문을 약간 이해하면 이해할 수 있습니다.