视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Node.js中对通用模块的封装方法_node.js
2020-11-27 21:24:02 责编:小采
文档


在Node.js中对模块载入和执行进行了包装,使得模块文件中的变量在一个闭包中,不会污染全局变量,和他人冲突。

前端模块通常是我们开发人员为了避免和他人冲突才把模块代码放置在一个闭包中。

如何封装Node.js和前端通用的模块,我们可以参考Underscore.js 实现,他就是一个Node.js和前端通用的功能函数模块,查看代码:

代码如下:
// 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._ = _;
}
通过判断exports是否存在来决定将局部变量 _ 赋值给exports,向后兼容旧的require() API,如果在浏览器中,通过一个字符串标识符“_”作为一个全局对象;完整的闭包如下:
代码如下:
(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);


通过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 (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);
从上面的几个例子可以看出,在封装Node.js和前端通用的模块时,可以使用以下逻辑:
代码如下:
if (typeof exports !== "undefined") {
exports.** = **;
} else {
this.** = **;
}
即,如果exports对象存在,则将局部变量装载在exports对象上,如果不存在,则装载在全局对象上。如果加上ADM规范的兼容性,那么多加一句判断:
代码如下:if (typeof define === "function" && define.amd){}

下载本文
显示全文
专题