Expressjs JavaScript 基础知识:exports = module.exports = createApplication;

Hel*_*rld 5 javascript node.js express

我不知道这个模式叫什么,如果知道的话我会直接查一下。

主要是,这是如何工作的?(此代码取自Express.js)

exports = module.exports = createApplication;
Run Code Online (Sandbox Code Playgroud)

我之前见过类似的模式,其中存在这种类型的引用变量链:

x = y = z
Run Code Online (Sandbox Code Playgroud)

我了解 Exports 与 module.exports,但查看上面的模式让我对它的实际工作原理产生疑问。

我遵循的一般经验法则是“module.exports”是真正的交易,而“exports”是它的帮助者,更多信息在这里

模块模式是这样的(不改变 module.exports)吗?

exports = module.exports = {};
Run Code Online (Sandbox Code Playgroud)

前任:

exports.name = 'hello' 
Run Code Online (Sandbox Code Playgroud)

结果到

exports = module.exports = {name: 'hello'}
Run Code Online (Sandbox Code Playgroud)

当您更改导出参考时会发生什么?

exports = {name: 'bob'}
Run Code Online (Sandbox Code Playgroud)

现在,当您添加到导出时,它将引用`{name:'bob'}并且不再与module.exports有任何联系?

btm*_*lls 5

你的直觉是正确的。我将从下往上工作:

Node.js 包装器

在运行任何文件之前,Node.js将整个脚本包装立即调用的函数表达式 (IIFE)中:

(function (exports, require, module, __filename, __dirname) {
    // ...script goes here...
});
Run Code Online (Sandbox Code Playgroud)

这就是它将moduleexports变量引入作用域的方式;它们没有什么比函数参数更特别的了。

使用exports

Node.js 文档module.exportsexports别名非常有帮助。首先,变量module.exportsexports变量都引用模块系统创建的同一个空对象。

如果一个模块只需要导出一个设置了一些属性的普通旧 JavaScript 对象,exports那么只需要:

exports.get = function(key) {
    // ...
};

exports.set = function(key, value) {
    // ...
};
Run Code Online (Sandbox Code Playgroud)

当代码require()进入此模块时,结果将类似于:

{
    get: [Function],
    set: [Function]
}
Run Code Online (Sandbox Code Playgroud)

更换module.exports

但是,Express 导出构造函数 ,createApplication作为根值。要导出函数本身,而不是仅仅将其分配给导出对象的属性,它必须首先完全替换导出的对象:

module.exports = createApplication;
Run Code Online (Sandbox Code Playgroud)

现在,exports尚未更新,仍然引用旧对象,而module.exports是对 的引用createApplication。但如果您继续阅读,您会注意到除了构造函数之外,Express 还导出其他几个属性。虽然将这些属性分配给 的新值上的属性就足够了module.exports,但重新分配的时间较短exports,使其再次成为 的别名module.exports,然后将这些属性分配给exports,这相当于将它们分配给module.exports

因此,这些示例在功能上是等效的:

module.exports = createApplication;

function createApplication() {
    // ...
}

module.exports.application = proto;
module.exports.request = req;
module.exports.response = res;
Run Code Online (Sandbox Code Playgroud)

但这一个不太冗长:

exports = module.exports = createApplication;

function createApplication() {
    // ...
}

exports.application = proto;
exports.request = req;
exports.response = res;
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,结果都是相同的,都是一个createApplication在根处命名的函数,其属性可用:

{
    [Function: createApplication]
    application: [Object],
    request: [Object],
    response: [Object],
    // ...a few other properties...
}
Run Code Online (Sandbox Code Playgroud)