27

我想创建模块来构建我的 NodeJS 应用程序,但我有点迷茫,而且我还没有找到任何(经过数小时的搜索)完全确定的主题。

假设我想创建一个“用户”模块,我可以使用以下代码在我的代码中创建新用户:

var newUser = new User();

理想情况下,我需要在我的代码顶部使用我的模块,例如:

var User = require('../lib/user');

这很好用。问题是,我应该如何构建用户模块?以下是最好的方法吗?

module.exports = function User()    {
    var authorized = false;
    var username = undefined;
    var password = undefined;
    var statistics = undefined;

    this.authorized = function()  {
        return authorized;
    }
    this.username = function()  {
        return username;
    }
    this.statistics = function()    {
        return statistics;
    }
}

我正在为我的各种模块变量编写 getter 和 setter,允许我隐藏我不想从其他代码意外访问的东西。但是,我以前这样做过:

function User() {
    this.authStatus = false;
    this.email;
    this.displayName;
    this.inSession;
}

User.prototype.isAuthenticated = function() {
    return(this.authStatus && this.email && this.displayName)
}

User.prototype.isInSession = function() {
    return(this.inSession && this.isAuthenticated());
}

exports.User = User;

这也有效,但有一个警告;我还没有找到从闭包中访问用户属性的方法。如果我的理解是正确的,那么对于第二个实现,我不能。这意味着如果我需要将一个函数作为回调传递给 db 库来编辑用户的属性,我不能。那看起来像:

User.prototype.login = function()    {
    db.doDbStuff('get user data query', function(_error, _result)    {
         this.username = _result[0].name; //this code will not work
    });
}

据我了解,该代码不起作用,因为“this”关键字在闭包的范围内,而不是用户。即使将代码放置在 User 函数中:

function User() {
    this.login = function()    { //you know

它行不通。

我想我的问题是,这个问题的最佳解决方案是什么?是我在第一个代码块中介绍的方法吗?这看起来相当麻烦和混乱,并且容易发生可变碰撞。我很害怕。

提前致谢!

4

3 回答 3

26

我通常采用第二种方法,将函数附加到原型上。

您遇到的变量“在闭包中不可用”的问题与原型无关。无论您如何构建它,您都会遇到同样的问题。

这与 javascript 经常令人困惑的动态有关thishttp ://robotlolita.me/2011/10/09/understanding-javascript-oop.html#sec-2-1

基本上,您需要执行以下操作:

User.prototype.login = function()    {
    var self = this // bind this to self so you have a reference to what `this` was

    db.doDbStuff('get user data query', function(_error, _result)    {
         self.username = _result[0].name; // self refers to the original `this`, so this works.
    });
}

您还可以选择使用 function.bind:https ://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

在绑定函数中, 的值this将是您提供给的任何值.bind(value)

User.prototype.login = function()    {
    db.doDbStuff('get user data query', (function(_error, _result)    { 
         this.username = _result[0].name; // bind fixes the original `this`, so this also works.
    }).bind(this));
}

无论您是使用function.bind还是self = this个人口味问题,但前几天我们在 freenode#nodejs 中进行了一些基准测试,发现bind()它比var self = this.

至于你最初关于如何构建模块的问题,github上有很多例子可以学习。只需找到您最喜欢的模块并检查它们的结构即可。我注意到许多人似乎更喜欢工厂而不是直接暴露构造函数(例如require('module').create())。你的来电。

于 2012-02-14T00:49:30.473 回答
12

作为一种不同的方法,我喜欢以下模式。

module.exports = 功能用户(数据){

    //这完全是私人的东西。

    变量私有变量;
    var username = data.username;
    var pass = data.pass; //ETC

    函数私有函数(){
    }

    返回 {
        登录:函数(cb){
            db.doStuff(用户名,通行证,cb);
        }
    };
};
于 2013-01-25T23:43:17.223 回答
2
User.prototype.login = function()    {
    var _this = this;
    db.doDbStuff('get user data query', function(_error, _result)    {
        _this.username = _result[0].name; //this code will now work
    });
}

你使用的'this'超出了它的范围,它是回调'this'

于 2012-02-14T00:39:43.207 回答