在Node.js中對模組載入和執行進行了包裝,使得模組檔案中的變數在一個閉包中,不會污染全域變量,和他人衝突。
前端模組通常是我們開發人員為了避免和他人衝突才把模組程式碼放置在一個閉包中。
如何封裝Node.js和前端通用的模組,我們可以參考Underscore.js 實現,他就是一個Node.js和前端通用的功能函數模組,查看程式碼:
// Creuseate a safe below.
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _objapp); = obj;
};
// Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we // backwards-compatibility for the old `require()` API. If we 're in
// the browser, add `_` as a global object via a string identifier,
// for Closure Compiler "advanced" mode.
if (type ) {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _; exports = module. 鎠{
root._ = _;
}
透過判斷exports是否存在來決定將局部變數_ 賦值給exports,向後相容於舊的require() API,如果在瀏覽器中,透過一個字串識別碼「_」作為一個全域物件;完整的閉包如下:
複製程式碼
// Baseline setup
// --------------
/ / Establish the root object, `window` in the browser, or `exports` on the server.
var root = this;
// Create a safe reference to the Underscore object for below below. 🎜> var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(objwr);
};
// Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API.
// the browser, add `_` as a global object via a string identifier,
// for Closure Compiler "advanced" mode.
if (typeof exports !== 'undefined' 🎜> if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _;
} exports = module.exports = _;
} 🎜 > root._ = _;
}
}).call(this);
透過function定義建置了一個閉包,call(this)是將function在this物件下調用,以避免內部變數污染到全域作用域。瀏覽器中,this指向的是全域物件(window物件),將“_”變數賦在全域物件上“root._”,以供外部呼叫。
和Underscore.js 類似的Lo-Dash,也是使用了類似的方案,只是相容了AMD模組載入的相容:
複製程式碼
程式碼如下:
;(function() {
/**Used as a safe reference for `undefined` in pre ES5 environments*/
var undefined;
/**Used to determine if values are of the language type Object*/
var objectTypes = {
'boolean': false,
'function': true,
'object': true,
'number': false,
'string': false,
'undefined': false
};
/**Used as a reference to the global object*/
var root = (objectTypes[typeof window] && window) || this;
/**Detect free variable `exports`*/
var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
/**Detect free variable `module`*/
var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
/**Detect the popular CommonJS extension `module.exports`*/
var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
/*--------------------------------------------------------------------------*/
// expose Lo-Dash
var _ = runInContext();
// some AMD build optimizers, like r.js, check for condition patterns like the following:
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// Expose Lo-Dash to the global object even when an AMD loader is present in
// case Lo-Dash was injected by a third-party script and not intended to be
// loaded as a module. The global assignment can be reverted in the Lo-Dash
// module by its `noConflict()` method.
root._ = _;
// define as an anonymous module so, through path mapping, it can be
// referenced as the "underscore" module
define(function() {
return _;
});
}
// check for `exports` after `define` in case a build optimizer adds an `exports` object
else if (freeExports && freeModule) {
// in Node.js or RingoJS
if (moduleExports) {
(freeModule.exports = _)._ = _;
}
// in Narwhal or Rhino -require
else {
freeExports._ = _;
}
}
else {
// in a browser or Rhino
root._ = _;
}
}.call(this));
再来看看Moment.js的封装闭包主要代码:
(function (未定義) {
var moment;
// nodeJS をチェック
var hasModule = (typeof module !== 'unknown' && module.exports);
/*************************************
露出の瞬間
******** ****************************/
function makeGlobal(deprecate) {
var warning = false, local_moment = moment;
/*global ender:false */
if (エンダーの種類!== '未定義') {
return;
}
// ここで、「this」はブラウザの「ウィンドウ」、またはサーバーの「グローバル」を意味します
// 「モーメント」を追加` 文字列識別子を介したグローバル オブジェクトとして、
// Closure Compiler の「上級」モード用
if (非推奨) {
this.moment = function () {
if (!warned && console && console.warn) {
warn = true;
console.warn(
「グローバル スコープを介した Moment へのアクセスは "
「非推奨であり、今後の「
」」で削除される予定ですrelease.");
}
return local_moment.apply(null, argument);
};
} else {
this['moment '] = 瞬間;
}
}
// CommonJS モジュールが定義されています
if (hasModule) {
module.exports = moment;
makeGlobal(true);
} else if (typeof define = == "function" &&define.amd) {
define("moment", function (require,exports, module) {
if (module.config().noGlobal !== true) {
// ユーザーが noGlobal を指定した場合、ユーザーは global を認識します
makeGlobal(module.config().noGlobal === unknown);
}
return moment;
});
} else {
makeGlobal();
}
}).call(this);
上の画面の例は、封入Node.jsとフロントエンドで見られます。汎用的なモジュールの場合は、次の逻辑を使用できます:
if ( typeofexports !== "未定義") {
exports.** = **;
} else {
this.** = **;
}
つまり、エクスポート オブジェクトが存在する場合は、局所的な値がエクスポート オブジェクトにロードされ、存在しない場合は、ローカル オブジェクト全体にロードされます。 🎜>
复制代码