我正在使用Node.js,Express.js和MongoDB创建应用程序。 我正在使用MVC模式,并且还有单独的路由文件。 我正在尝试创建一个Controller类,其中一个方法调用在其中声明的另一个方法。但我似乎无法做到这一点。我得到“无法读取未定义的属性”。
index.js文件
let express = require('express');
let app = express();
let productController = require('../controllers/ProductController');
app.post('/product', productController.create);
http.createServer(app).listen('3000');
ProductController.js文件
class ProductController {
constructor(){}
create(){
console.log('Checking if the following logs:');
this.callme();
}
callme(){
console.log('yes');
}
}
module.exports = new ProductController();
当我运行时,我收到以下错误消息:
Cannot read property 'callme' of undefined
我已经运行了这段代码,只需要进行一些修改,如下所示,它可以工作。
class ProductController {
constructor(){}
create(){
console.log('Checking if the following logs:');
this.callme();
}
callme(){
console.log('yes');
}
}
let product = new ProductController();
product.create();
为什么一个工作而另一个工作? 帮助!
答案 0 :(得分:4)
您的方法是being rebound to the Layer
class within express,失去了原来的背景。表达路由的方式是将每个路由包装在Layer
类中,该类将路由回调分配给自己:
this.handle = fn;
这就是问题出现的地方,这个赋值会自动将函数上下文重新绑定到Layer
。这是一个展示问题的简单示例:
function Example() {
this.message = "I have my own scope";
}
Example.prototype.logThis = function() {
console.log(this);
}
function ReassignedScope(logThisFn) {
this.message = "This is my scope now";
// simulation of what is happening within Express's Layer
this.logThis = logThisFn;
}
let example = new Example()
let scopeProblem = new ReassignedScope(example.logThis);
scopeProblem.logThis(); // This is my scope now
其他人已经指出了解决方案,即将您的方法显式绑定到ProductController
实例:
app.post('/product', productController.create.bind(productController));
答案 1 :(得分:2)
当您将create
方法作为方法传递时,可能会按照您的预期在不同的上下文(this
)中调用它。你可以绑定它:
app.post('/product', productController.create.bind(productController));
还有很多其他方法可以确保this
引用正确的对象。
E.g。用功能(箭头或经典)包装它:
app.post('/product', (...args) => productController.create(...args));
或者在构造函数中绑定方法:
constructor() {
this.create = this.create.bind(this);
}