module.exports在node.js应用程序中冲突/被覆盖

Gre*_*reg 3 javascript node.js express node-modules

我想我很难误解如何使用module.exports.似乎每个模块都覆盖了最后一个模块吐出的内容.

app.js:

var express = require("express")
    , app = express()
    , routes = require('routes')
    , server = app.listen(1337, "0.0.0.0")
    , io = require('socket.io').listen(server)
    , redis = require("redis")
    , client = redis.createClient();
Run Code Online (Sandbox Code Playgroud)

var moduleA = require("./moduleA")(io, client); (需要传递socket.io和redis客户端)

var moduleB = require("./moduleB")(io, client); (相同)

moduleA.js:

module.exports = function(io, client){ 
    this.test = 'foo';
    return this;
};
Run Code Online (Sandbox Code Playgroud)

moduleB.js:

module.exports = function(io, client){ 
    this.test = 'bar';
    return this;
};
Run Code Online (Sandbox Code Playgroud)

回到app.js:

console.log(moduleB.test);(打印"酒吧")

console.log(moduleA.test);(打印"酒吧")

有人可以解释我做错了吗?我想不出有任何其他方法可以做到这一点,因为exports帮助器(?)本身似乎不接受参数.

Dom*_*nic 8

您正在导出构造函数.你需要构建它,而不是调用它.

更改

var moduleA = require("./moduleA")(io, client);
Run Code Online (Sandbox Code Playgroud)

var moduleA = new (require("./moduleA"))(io, client);
Run Code Online (Sandbox Code Playgroud)

或(为清楚起见)

var ModuleA = require("./moduleA");
var a = new ModuleA(io, client);
Run Code Online (Sandbox Code Playgroud)

您所看到的是在sloppy模式下将构造函数作为函数调用时的常见行为:this引用全局对象.因此,当然从两个位置修改全局对象将相互覆盖,并且返回this将仅返回全局对象.您可以自己测试:使用您当前的代码,

moduleA === moduleB === this === global
Run Code Online (Sandbox Code Playgroud)

防止自己像这样再次射击自己的一种方法是使用严格模式而不是马虎模式.为此,请添加该行

"use strict";
Run Code Online (Sandbox Code Playgroud)

在您编写的每个模块的顶部(在任何其他代码之前).在严格模式下,this对构造称为不new就是undefined,所以你会得到一个较早和更容易理解的错误.

严格模式有很多这样的好处; 有关概述,请参阅[1],[2],[3].


另一种解决方案是完全停止使用构造函数,而是使用工厂函数.这看起来像:

module.exports = function (io, client) {
    var result = {};
    result.test = "foo";
    return result;
};
Run Code Online (Sandbox Code Playgroud)

无论如何,你似乎都试图做这样的事情,因为return this即使你在构造函数中这样做是完全没必要的.您可以停止使用this并使用您控制下的实际对象,而不是根据您的函数是被调用还是构造而改变其语义的对象.