Javascript 构建NodeJS模块-变量和方法
我想创建模块来构造我的NodeJS应用程序,但是我有点迷路了,而且我还没有找到任何关于这个主题的完全确定的东西(经过数小时的搜索) 假设我想创建一个“用户”模块,通过该模块,我可以使用以下方法在代码中创建新用户:Javascript 构建NodeJS模块-变量和方法,javascript,node.js,closures,commonjs,Javascript,Node.js,Closures,Commonjs,我想创建模块来构造我的NodeJS应用程序,但是我有点迷路了,而且我还没有找到任何关于这个主题的完全确定的东西(经过数小时的搜索) 假设我想创建一个“用户”模块,通过该模块,我可以使用以下方法在代码中创建新用户: var newUser = new User(); var User = require('../lib/user'); User.prototype.login = function() { db.doDbStuff('get user data query', f
var newUser = new User();
var User = require('../lib/user');
User.prototype.login = function() {
db.doDbStuff('get user data query', function(_error, _result) {
this.username = _result[0].name; //this code will not work
});
}
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.
});
}
理想情况下,我会要求在代码顶部使用以下模块:
var newUser = new User();
var User = require('../lib/user');
User.prototype.login = function() {
db.doDbStuff('get user data query', function(_error, _result) {
this.username = _result[0].name; //this code will not work
});
}
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.
});
}
这很有效。问题是,我应该如何构造用户模块?以下是最好的方法吗
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库来编辑用户的属性,我就不能。这看起来像:
var newUser = new User();
var User = require('../lib/user');
User.prototype.login = function() {
db.doDbStuff('get user data query', function(_error, _result) {
this.username = _result[0].name; //this code will not work
});
}
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.
});
}
据我所知,代码不起作用,因为“this”关键字在闭包的范围内,而不是用户。即使代码要放在用户函数中:
function User() {
this.login = function() { //you know
这是行不通的
我想我的问题是,这个问题的最佳解决方案是什么?这是我在第一个代码块中介绍的方法吗?这看起来相当麻烦和混乱,而且容易发生冲突。我很害怕
提前谢谢
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'
我通常使用第二种方法,将函数附加到原型
变量“在闭包中不可用”的问题与原型无关。无论采用哪种方式,你都会遇到同样的问题
这与javascript经常混淆的动态有关:
基本上,您需要做如下操作:
var newUser = new User();
var User = require('../lib/user');
User.prototype.login = function() {
db.doDbStuff('get user data query', function(_error, _result) {
this.username = _result[0].name; //this code will not work
});
}
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:
在绑定函数中,此
的值将是您提供给的任何值。绑定(值)
:
无论您是使用function.bind
还是self=this
都是一个个人喜好的问题,但前几天我们在freenode中做了一些基准测试,发现bind()
比var self=this
慢20多倍
至于您最初提出的关于如何构造模块的问题,github上有很多示例可供学习。只需找到您最喜欢的模块并检查它们是如何构建的。我注意到许多人似乎更喜欢工厂而不是直接公开构造函数(例如,require('module').create()
)。你的电话。作为一种不同的方式,我喜欢以下模式
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);
}
};
};
module.exports=函数用户(数据){
//这完全是私事。
私有风险;
var username=data.username;
var pass=data.pass;//等
函数privateFunc(){
}
返回{
登录:功能(cb){
db.doStuff(用户名、密码、cb);
}
};
};
如果这些都没有意义,我提前道歉,我只是吃了一些治智齿的止痛药,感觉有点轻,有点怪。似乎更多的是在javascript架构领域,而不是一般的node.js。值得注意的是,在你的两个例子中,变量都不是私有的。你应该看看:我想唐所指的页面已经移动到了哦。这是如此的聪明和简单!天哪谢谢当它发生意外变化时,它的动态特性确实令人困惑,但当你真正有意使用它时,它也是Javascript最强大的功能之一。是的,Javascript给了我一种非常奇怪的感觉,非常强大,令人敬畏,再加上“哦,我的天,这太荒谬了。”--有没有什么方法可以推荐使用prototype方法来保持某些成员的私有性?@Matt:您可以使用Python的方法:在其前面加下划线,并将其用作约定“这是私有的;除非您知道自己在做什么,否则不要碰它”。只要不将它们添加到导出/此对象中,它们将是私有的。您可以使用bind()
调用当前对象上的方法。但是请注意,module.require将始终返回相同的对象,因此这些变量本质上是“静态的”。更难的问题是如何创建私有实例变量。我想大多数人都会选择更简单的“this.\u thisIsPrivate”方法(丑陋但有效),但你也可以这样做:我也喜欢这样。但这种方法只适用于单身人士,对吗?您不能以这种方式实例化。@owzim此模式实际上不仅适用于单例,它看起来非常类似于module.exports=(function(){…})();这是一个单一的模式,因为它直接执行函数。但是这个答案中的代码不是单例代码,因为您现在可以执行require('data')(my_instance_data);