我想创建模块来构建我的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
它不会起作用。
我想我的问题是,这个问题的最佳解决方案是什么?这是我在第一个代码块中提出的方法吗?这似乎相当麻烦和混乱,容易发生变量冲突。我很害怕。
提前致谢!
答案 0 :(得分:25)
我通常采用第二种方法,将功能附加到原型上。
您对变量“无法在闭包中使用”所遇到的问题与原型无关。无论你如何构建它,你都会遇到同样的问题。
这与javascript的混乱动态this
有关:
http://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()
是20次慢于var self = this
。
关于如何构建模块的原始问题,有很多例子可以在github上学习。只需找到您喜欢的模块并检查它们的结构。我注意到许多人似乎更喜欢工厂而不是直接暴露构造函数(例如require('module').create()
)。你的电话。
答案 1 :(得分:12)
作为一种不同的方法,我是以下模式的粉丝。
module.exports = function User(data) { //this properly private stuff. var privateVar; var username = data.username; var pass = data.pass; //etc function privateFunc() { } return { login: function(cb) { db.doStuff(username, pass, cb); } }; };
答案 2 :(得分: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'
。