如何从节点.js模块正确返回一组实例
How to properly return a set of instances from a node.js module
我想实例化一系列对象,每个对象公开一个函数,然后将它们作为节点.js模块返回,以便在项目中的其他地方使用。
我尝试使用这个:
function Role(id, ext) {
this.id = id;
this.ext = ext || [];
}
Role.prototype.filter = function(req, res, next) {
if (!req.user)
return res.status(401).send({
"message": "unauthorized"
});
if (req.user.role !== this.id && this.ext.indexOf(req.user.role) < 0)
return res.status(403).send({
"mesage": "forbidden"
});
return next();
};
var Roles = {
admin: new Role("admin"),
member: new Role("member", ["admin"]) // admin extends member
};
module.exports = Roles;
这不起作用,this.id 从我的其他模块中使用的任何实例调用过滤器时,没有定义 this.ext。
相反,这有效:
var Role = function(id, ext) {
var self = this;
self.id = id;
self.ext = ext || [];
self.filter = function(req, res, next) {
if (!req.user)
return res.status(401).send({
"message": "unauthorized"
});
if (req.user.role !== self.id && self.ext.indexOf(req.user.role) < 0)
return res.status(403).send({
"mesage": "forbidden"
});
return next();
};
}
var Roles = {
admin: new Role("admin"),
member: new Role("member", ["admin"]) // admin extends member
};
module.exports = Roles;
。但看起来要不优雅得多。
第一个构造有什么问题?我对javascipt oop很陌生,但它看起来与我在这里和那里看到的关于如何使用这种语言定义类和实例方法的内容非常相似。
更新
根据要求并澄清一下,这是我的另一个模块中如何调用函数:
router.get('/', filter, Roles.admin.filter, function(req, res, next) {
// doing some business
});
你正在失去函数的上下文,所以你必须bind
这个上下文,或者在调用时表示它
绑定示例:
function Role(id, ext) {
this.id = id;
this.ext = ext || [];
// you should understand, that bind creates new function, this time it ok.
this.filter = this.filter.bind(this);
}
Role.prototype.filter = function(req, res, next) {
if (!req.user)
return res.status(401).send({
"message": "unauthorized"
});
if (req.user.role !== this.id && this.ext.indexOf(req.user.role) < 0)
return res.status(403).send({
"mesage": "forbidden"
});
return next();
};
var Roles = {
admin: new Role("admin"),
member: new Role("member", ["admin"]) // admin extends member
};
module.exports = Roles;
"平均"示例:
使用初始代码,但在调用方法时,请使用call
或apply
或bind
var filter = admin.filter;
filter.call(admin, req, res, next); // just call
filter.call(admin, [req, res, next]); // good when you are using arguments
server.on('connect', admin.filter.bind(admin)); //if you need it as callback
setTimeout(admin.filter.bind(admin, req, res, next)); // if you know
// that one, who will call calback will not pass arguments itself.
this
根据 函数的调用方式更改其值。
与其他语言相比,this
关键字在 JavaScript 中的工作方式不同。我建议您阅读MDN网站上的指南。
在这两种情况下,this
都设置为调用者的范围(我想是像 restify 或 expressjs 这样的库)。
您可以验证是否执行
Role.prototype.filter = function(req, res, next) {console.log(this)}
在第二种情况下,您可以使用self
来保存this
的上下文。如果您尝试使用this
您将看到this
的值与第一个示例相同。
因此,您的两个示例以相同的方式工作,但在第二个示例中,您使用self = this
作为解决方法。
解决方法
Javascript 提供了 3 个函数来改变这个值,强制函数的作用域:apply()
、call()
和 bind()
。
在您的情况下,我很确定bind()
是最佳选择。
在你的代码中的某个地方,根据你正在使用的库,你有类似的东西:
server.get('/route', Roles.filter);
您需要将其更改为
server.get('route', Roles.filter.bind(Roles));
现在,不知道你如何调用函数,我很确定这行不通,但无论如何,你需要的是作为bind()
类角色实例的参数传递。这样this
将设置为该角色实例的值。
bind()、apply() 和 call() 之间的区别
我说我认为你需要使用 bind(),因为它是三个函数中唯一一个不调用函数,而只是设置范围。在您的情况下,我认为您正在使用库来提供 API(由于 req、res、next),因此您不想调用该函数,只需引用它。
call() 和 apply() 改为调用函数。它们之间的唯一区别是你传递参数的方式:call()
接受参数列表,apply()
数组:
function.call(scope, arg1, arg2, arg3);
function.apply(scope, [arg1, arg2, arg3]);
- fluxxor向一个flux实例添加一组以上的操作
- 我们怎样才能将内含子J用于一组特定的元素
- 使用linq.js按当前日期订购一组momentjs日期
- 正则表达式,从一组关键字中获取奇数
- 创建一组元素JointJS
- 如何在javascript中获取一组复选框值
- 一组(共组..)
- 使用JS将页面中的每个字母设置为随机颜色.为什么在页面的每个打开标记之前总是有一组额外的span标记
- 在一组复选框中,一次只允许选择一个
- 为什么在fabricjs中可选择的不适用于一组圆
- 如何在不刷新页面的情况下每次单击一组选项卡时刷新视图内容窗格
- 从一组具有相同起始和结束的所有段落的段落中提取包含特定字符串的段落
- 简单的Javascript文本编辑器或一组函数
- 基于日期范围的一组日期范围内的天数
- 处理对象数组并将它们以 4 个为一组进行分配
- 如何在 Javascript 中用一组字符拆分子字符串上的字符串
- 使一组对象与 jQuery 一起拖动
- 使用第 n 个类型设置一组八个元素的样式
- 如何检查一个对象是否是JavaScript中某一组原型的实例?
- 如何从节点.js模块正确返回一组实例