【问题标题】:Create a copy of a module instead of an instance in Node.js在 Node.js 中创建模块的副本而不是实例
【发布时间】:2014-04-04 14:19:00
【问题描述】:

这将是我在 stackoverflow 上的第一个问题,希望一切顺利。 我一直在开发一个游戏(使用 corona SDK),我使用 Node.js 编写了一个小型服务器来处理我的客户端之间的一些聊天消息,那里没有问题。 现在我正在努力扩展这个小服务器来做更多的事情,我想做的是创建一个外部文件(模块),它将保存一个对象,该对象具有代表房间所需的所有函数和变量我的游戏“大厅”,两个人可以进入其中对战,每次我有两个玩家准备玩时,我都会为他们创建这个空房间的副本,然后在那个房间初始化游戏. 所以我在我的主项目文件中有一个数组,每个单元格都是一个房间,我的计划是将我的模块导入到那个数组中,然后我可以在那个特定的“房间”中初始化游戏,玩家会玩,游戏会继续进行,一切都会好起来的……但是……我在 main.js 中的代码:

var new_game_obj = require('./room.js');

games[room_id] = new_game_obj();

games[room_id].users = [user1_name,user2_name];

现在,在我的 room.js 中,我有类似的东西:

var game_logistics = {};

game_logistics.users = new Array();

game_logistics.return_users_count = function(){
    return game_logistics.users.length;
}

module.exports = function() {
    return game_logistics;
}

到目前为止一切顺利,而且这项工作也很好,我可以简单地去:

games[room_id].return_users_count()

我会得到 0、1 或 2,当然这取决于有多少用户加入了这个房间。 一旦我打开一个新房间,问题就开始了,因为 Node.js 将实例化我创建的模块而不复制它,如果我现在创建一个新房间,即使我消除和/或删除了旧房间,它将包含我已经更新的旧房间的所有信息,而不是新的洁净室。示例:

var new_game_obj = require('./room.js');

games["room_1"] = new_game_obj();
games["room_2"] = new_game_obj();

games["room_1"].users = ["yuval","lahav"];

_log(games["room_1"].return_user_count()); //outputs 2...
_log(games["room_2"].return_user_count()); //outputs 2...

即使这样做:

var new_game_obj = require('./room.js');
games["room_1"] = new_game_obj();

var new_game_obj2 = require('./room.js');
games["room_2"] = new_game_obj2();

games["room_1"].users = ["yuval","lahav"];

_log(games["room_1"].return_user_count()); //outputs 2...
_log(games["room_2"].return_user_count()); //outputs 2...

给出相同的结果,在我制作的所有“副本”中,它都是同一模块的相同实例。 所以我的问题就这么简单,我如何创建原始模块的“干净”副本,而不是一遍又一遍地实例化它,最终实际上只有一个凌乱的房间?

【问题讨论】:

    标签: javascript node.js object module instance


    【解决方案1】:

    您正在做的是(用返回的内容替换您的 require() 调用);

    var new_game_obj = function() {
        return game_logistics;
    }
    

    因此,每次调用new_game_obj,都会返回game_logistics相同实例。

    相反,您需要让new_game_obj 返回game_logistics 实例;

    // room.js
    function Game_Logistics() {
        this.users = [];
    
        this.return_users_count = function(){
            return this.users.length;
        };
    }
    
    module.exports = function() {
        return new Game_Logistics(); 
    }
    

    这是一个相当大的转变。您会看到我们在 module.exports 中的 Game_Logistics 上使用 new 以在每次调用时返回 Game_Logisticsnew 实例。

    您还会看到在Game_Logistics 内部,this 被到处使用,而不是Game_Logistics;这是为了确保我们引用了Game_Logistics 的正确实例,而不是构造函数。

    我还将您的 game_logistics 函数大写以遵守广泛遵循的命名约定,即构造函数应大写 (more info)。

    当您使用多个函数实例时,建议您利用 JavaScript 中的原型链。您可以仔细阅读有关“javascript 原型继承*”的各种文章(例如 this one),但目前,以上内容将满足您的需求。

    【讨论】:

    • 是的,学习如何正确使用new 关键字并编写“正确的”javascript 类而不是对象字面量。查看this article on javascript classes,就您可用的选项以及它们的不同之处进行一些很好的讨论。
    • 感谢您提供的信息,这似乎有效,对不起,我的 javascript 不够“合适”,我来自 actionscript/lua/php 背景,虽然我曾经在 javascript 中使用过, html 和 xml 过去,我从来都不是“专家”,但我在一些好人的帮助下边学习边学习,感谢链接,我会尽快阅读这些链接! :)
    • @Yuval:不用道歉,每个人都曾经是“新人”:)。
    • @Jason 感谢文章的链接,它提供的信息量非常大,简短而中肯,并提供了我所缺少的信息。
    • 是的,当我学习这些东西时,它也帮助了我。我开始将我的对象编写为文字,就像您在原始代码中所做的那样,我并不完全了解如何使用原型设计策略,或者为什么我会在 javascript 中编写足够复杂的东西来要求它(在我开始使用 node 之前) )。使用这两种方法是有原因的,但随着时间的推移,我越来越清楚原型策略在更多时候更有用。
    猜你喜欢
    • 2015-11-30
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 2012-12-19
    • 1970-01-01
    相关资源
    最近更新 更多