Modulladen und -ausführung werden in Node.js gepackt, sodass die Variablen in der Moduldatei geschlossen sind und keine globalen Variablen verschmutzen oder mit anderen in Konflikt geraten.
Bei Frontend-Modulen platzieren unsere Entwickler den Modulcode normalerweise in einem Abschluss, um Konflikte mit anderen zu vermeiden.
Wie man Module kapselt, die Node.js und dem Front-End gemeinsam sind, können wir auf die Implementierung von Underscore.js verweisen, einem funktionalen Funktionsmodul, das Node.js und dem Front-End gemeinsam ist. Sehen Sie sich den Code an:
// Create a safe reference to the Underscore object for use below. var _ = function(obj) { if (obj instanceof _) return obj; if (!(this instanceof _)) return new _(obj); this._wrapped = obj; }; // Export the Underscore object for **Node.js**, with // 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 (typeof exports !== 'undefined') { if (typeof module !== 'undefined' && module.exports) { exports = module.exports = _; } exports._ = _; } else { root._ = _; }
Bestimmen Sie, ob Exporte die lokale Variable _ zugewiesen werden sollen, indem Sie beurteilen, ob Exporte vorhanden sind. Abwärtskompatibel mit der alten require()-API. Wenn im Browser, übergeben Sie eine Zeichenfolgenkennung „_“ als globales Objekt. Vollständiger Abschluss Wie folgt:
(function() { // 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 use below. var _ = function(obj) { if (obj instanceof _) return obj; if (!(this instanceof _)) return new _(obj); this._wrapped = obj; }; // Export the Underscore object for **Node.js**, with // 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 (typeof exports !== 'undefined') { if (typeof module !== 'undefined' && module.exports) { exports = module.exports = _; } exports._ = _; } else { root._ = _; } }).call(this);
Ein Abschluss wird durch die Funktionsdefinition erstellt. call(this) ruft die Funktion unter diesem Objekt auf, um zu verhindern, dass interne Variablen den globalen Bereich verunreinigen. Im Browser zeigt dieser auf das globale Objekt (Fensterobjekt) und bei externen Aufrufen wird die Variable „_“ dem globalen Objekt „root._“ zugewiesen.
Lo-Dash, das Underscore.js ähnelt, verwendet ebenfalls eine ähnliche Lösung, ist jedoch mit dem Laden von AMD-Modulen kompatibel:
;(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));
Werfen wir einen Blick auf den Hauptcode des Kapselungsabschlusses von Moment.js:
(function (undefined) { var moment; // check for nodeJS var hasModule = (typeof module !== 'undefined' && module.exports); /************************************ Exposing Moment ************************************/ function makeGlobal(deprecate) { var warned = false, local_moment = moment; /*global ender:false */ if (typeof ender !== 'undefined') { return; } // here, `this` means `window` in the browser, or `global` on the server // add `moment` as a global object via a string identifier, // for Closure Compiler "advanced" mode if (deprecate) { this.moment = function () { if (!warned && console && console.warn) { warned = true; console.warn( "Accessing Moment through the global scope is " + "deprecated, and will be removed in an upcoming " + "release."); } return local_moment.apply(null, arguments); }; } else { this['moment'] = moment; } } // CommonJS module is defined 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) { // If user provided noGlobal, he is aware of global makeGlobal(module.config().noGlobal === undefined); } return moment; }); } else { makeGlobal(); } }).call(this);
Wie aus den obigen Beispielen ersichtlich ist, gilt beim Kapseln von Modulen, die Node.js und dem Front-End gemeinsam sind, die folgende Logik kann verwendet werden:
if (typeof exports !== "undefined") { exports.** = **; } else { this.** = **; }
Das heißt, wenn das Exportobjekt vorhanden ist, werden die lokalen Variablen auf das Exportobjekt geladen, und wenn sie nicht vorhanden sind, werden sie auf das globale Objekt geladen. Wenn Sie die Kompatibilität der ADM-Spezifikation hinzufügen, fügen Sie ein weiteres Urteil hinzu:
if (typeof define === "function" && define.amd){}
Weitere Artikel zur Kapselungsmethode allgemeiner Module in Node.js finden Sie auf der chinesischen PHP-Website!