모듈 로딩과 실행은 Node.js에 패키징되어 있어 모듈 파일의 변수는 클로저로 처리되어 전역 변수를 오염시키거나 다른 변수와 충돌하지 않습니다.
프론트엔드 모듈의 경우 개발자는 일반적으로 다른 개발자와의 충돌을 피하기 위해 모듈 코드를 클로저에 배치합니다.
Node.js와 프런트엔드에 공통된 모듈을 캡슐화하는 방법은 Node.js와 프런트엔드에 공통된 기능적 기능 모듈인 Underscore.js 구현을 참조하고 코드를 보면 됩니다.
// 밑줄에 대한 안전한 참조를 만듭니다. 아래에서 사용할 객체.
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
//
을 사용하여 **Node.js**에 대한 Underscore 객체를 내보냅니다. // 이전 `require()` API에 대한 하위 호환성을 제공합니다. .
// 브라우저에 있는 경우 문자열 식별자를 통해 `_`를 전역 개체로 추가합니다.
// Closure Compiler "고급" 모드의 경우.
if (typeof 내보내기 !== '정의되지 않음' ) {
if (모듈 유형 !== '정의되지 않음' && module.exports) {
내보내기 = module.exports = _;
}
내보내기._ = _;
} else {
root._ = _;
}
로컬 변수 _가 내보내기에 할당되었는지 확인하기 위해 내보내기가 존재하는지 확인합니다. 이는 이전 require(와 호환됩니다. ) API에서 문자열 식별자 "_"를 통한 전역 객체인 경우 전체 폐쇄는 다음과 같습니다.
(function() {
// 기준 설정
// ------------ --
/ / 루트 객체를 설정합니다. 브라우저에서는 'window', 서버에서는 'exports'입니다.
var root = this;
// 안전한 참조 생성 아래에서 사용하기 위해 Underscore 객체에.
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
//
// 이전 `require( )` API에 있는 경우
// 브라우저에서 문자열 식별자를 통해 `_`를 전역 개체로 추가합니다.
// Closure Compiler "고급" 모드의 경우.
if (내보내기 유형 !== '정의되지 않음') {
if (모듈 유형 !== '정의되지 않음' && module.exports) {
내보내기 = module.exports = _;
}
내보내기._ = _ ;
} else {
root._ = _;
}
}).call(this);
클로저는 다음 함수를 통해 구성됩니다. call(this)은 내부 변수가 전역 범위를 오염시키는 것을 방지하기 위해 이 객체에서 호출되는 함수입니다. 브라우저에서 이는 전역 객체(window 객체)를 가리키며, 외부 호출을 위해 "_" 변수가 전역 객체 "root._"에 할당됩니다.
Underscore.js와 유사한 Lo-Dash도 비슷한 솔루션을 사용하지만 AMD 모듈 로딩과 호환됩니다.
;(function() {
/**ES5 이전 환경에서 '정의되지 않음'에 대한 안전한 참조로 사용됨*/
var undefine;
/**값이 언어 유형 객체인지 확인하는 데 사용됩니다.*/
var objectTypes = {
'부울': false,
'함수': true,
'객체': true,
'번호': false,
'문자열': false,
'정의되지 않음 ': false
};
/**전역 개체에 대한 참조로 사용됩니다.*/
var root = (objectTypes[typeof window] && window) || this;
/**자유 변수 '내보내기' 감지 */
var freeExports = objectTypes[수출 유형] && 수출 && !exports.nodeType && 수출;
/**자유 변수 '모듈' 감지*/
var freeModule = objectTypes[모듈 유형] && 모듈 && !module.nodeType && module;
/**인기 있는 CommonJS 확장 `module.exports` 감지*/
var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
/*-- ------------------------------------- -------*/
// Lo-Dash 노출
var _ = runInContext();
// r.js와 같은 일부 AMD 빌드 최적화 프로그램은 다음과 같은 조건 패턴을 확인합니다.
if (typeof 정의 == 'function' && typeof 정의.amd == 'object' && 정의.amd) {
// AMD 로더가 있는 경우에도 Lo-Dash를 전역 개체에 노출합니다.
// Lo-Dash가 타사 스크립트에 의해 삽입되었으며 의도되지 않은 경우
// 다음과 같이 로드되었습니다. 모듈. 전역 할당은 Lo-Dash
// `noContric()` 메서드를 통해 모듈에서 되돌릴 수 있습니다.
root._ = _;
// 익명 모듈로 정의하므로, 경로 매핑을 통해
// "밑줄" 모듈로 참조
정의(function() {
return _;
});
}
// 확인 for 빌드 최적화 프로그램이 `exports` 객체를 추가하는 경우 `define` 뒤 `exports`
else if (freeExports && freeModule) {
// Node.js 또는 RingoJS
if (moduleExports) {
(freeModule.exports = _)._ = _;
}
// Narwhal 또는 Rhino에서 -require
else {
freeExports._ = _;
}
}
else {
// 브라우저 또는 Rhino에서
root._ = _;
}
}.call(this));
再来看看Moment .js의 封装闭包主要代码:
(함수 (정의되지 않음) {
var moment;
// nodeJS를 확인하세요
var hasModule = (모듈 유형 !== '정의되지 않음' && module.exports);
/************************************
노출 순간
******** ****************************/
function makeGlobal(deprecate) {
var warninged = false, local_moment = moment;
/*global ender:false */
if (typeof ender !== '정의되지 않음') {
return;
}
// 여기서 `this`는 브라우저에서는 `window`를 의미하고, 서버에서는 `global`을 의미합니다
// `moment 추가 ` 문자열 식별자를 통한 전역 개체로,
// Closure Compiler "고급" 모드용
if (사용 중단) {
this.moment = function () {
if (!warned && console && console.warn) {
warninged = true;
console.warn(
'전역 범위를 통해 Moment에 액세스하는 방법은 "
"더 이상 사용되지 않으며 향후 "
에서 제거될 예정입니다. ' release.");
}
return local_moment.apply(null, 인수);
};
} else {
'] = 순간;
}
}
// CommonJS 모듈이 정의됨
if (hasModule) {
module.exports = moment;
makeGlobal(true);
} else if (typeof 정의 = == "함수" && 정의.amd) {
정의("순간", 함수(요구, 내보내기, 모듈) {
if (module.config().noGlobal !== true) {
// 사용자가 noGlobal을 제공한 경우 전역을 인식합니다
makeGlobal(module.config().noGlobal === undefine);
}
return moment;
});
} else {
makeGlobal();
}
}).call(this);
从上面的几个例子可以看流,封装Node.js와前端일반적으로 사용되는 模块时,可以使用以下逻辑:
if ( 내보내기 유형 !== "정의되지 않음") {
내보내기.** = **;
} else {
this.** = **;
}
即,如果수출이 对象存재,则将局부变weight装载이수출对象上, 如果不存재, 则装载가전체局对象上에있습니다.加一句判断:
if (typeof 정의 === "function" && 정의.amd){}