引用导出属性的多种方式之间的区别

Difference between multiple ways of referencing exported attribute

我正在使用 socket.io 并且需要导出 io 对象以便在其他文件中使用。控制器 A 工作并成功发出消息。奇怪的是控制器 B 和 C 没有正确引用 .io。三种引用方式有区别吗.io?

// index.js

exports.register = function (server, options, next) {
    var onlineUsers = {};

    var io = require('socket.io')(server.select('collaboration').listener);

    io.on('connection', function (socket) {
        socket.on('is_online', Handlers.is_online.bind(null, socket));
        socket.on('disconnect', Handlers.is_offline.bind(null, socket));
    });

    exports.io = io;

    next();
};

// controllerA.js
var io = require('./collaboration/index');
function testFunc() {
    io.io.emit('testing', {data: 'some data'});
}
// controllerB.js
var io = require('./collaboration/index').io;
function testFunc() {
    io.emit('testing', {data: 'some data'});
}
// controllerC.js
var index = require('./collaboration/index');
var io = index.io;
function testFunc() {
    io.emit('testing', {data: 'some data'});
}

这与时间有关:exports.io 仅在调用 register() 时创建。在此之前,exports.io 未定义。

这也反映在您的控制器中:

  • controllerA 存储对 index.jsexports 对象的引用。在您需要 index.js 时,exports.io 尚不存在,但这不是问题,因为您稍后在 testFunc 中引用它( 意味着 register() 必须在 testFunc 之前调用,否则 io.io 仍然未定义);
  • controllerBcontrollerC 在调用 require 时直接引用 exports.io。不过在那个时候,它还不存在。换句话说,他们存储了一个未定义的引用,因此他们的 testFunc 失败了;

这是对正在发生的事情的简化:

// controllerA
var obj = {};
var io  = obj;
obj.io  = 'hello';
console.log(io.io);

// controllerB
var obj = {};
var io  = obj.io;
obj.io  = 'hello';
console.log(io);

// controllerC
var obj   = {};
var index = obj;
var io    = index.io;
obj.io    = 'hello';
console.log(io);

此记录:

hello
undefined
undefined