javascript - 为什么在此类方法中未定义 "this"?

标签 javascript node.js this undefined es6-class

我试图搜索似乎是整个互联网,但我仍然对我正在为微服务编写的 JS 类的问题感到烦恼(仍在学习中)。

所以,我尝试在实例化对象上调用类方法,根据我的知识和我的(我认为是错误的)单元测试,它应该可以工作。

好吧,我将从收到的错误开始:

    GET /api/users 500 2.863 ms - 2649
TypeError: Cannot read property 'repository' of undefined
    at list (C:\Users\<user>\Documents\Programming\node\kaguwa-ngn\kaguwa-user-service\controllers\user-controller.js:20:9)
    at Layer.handle [as handle_request] (C:\Users\<user>\Documents\Programming\node\kaguwa-ngn\kaguwa-user-service\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\Users\<user>\Documents\Programming\node\kaguwa-ngn\kaguwa-user-service\node_modules\express\lib\router\route.js:137:13)

(还有更多)。

代码调用代码:

user-controller.js

'use strict';

var utils = require('./utils');

class UserController {

  constructor(repository) {
    this.repository = repository || {};
  }

  /**
   * 
   * Lists all users.
   * 
   * @param {object} req 
   * @param {object} res 
   */
  list(req, res) {

    this.repository.list(function (err, users) {
      if (err) return res.status(500).json(utils.createError(500));

      if (Object.keys(users).length !== 0) {
        res.json(users);
      } else {
        res.status(404).json(utils.createNotFound('user', true));
      }
    });
  }
// more code
}

module.exports = UserController

Controller 调用者

user-api.js


'use strict';

var express = require('express');
var UserController = require('../controllers/user-controller');

var router = express.Router();

module.exports = function (options) {

  var userController = new UserController(options.repository);

  router.get('/users', userController.list);
  // Mode code

  return router;
};

我真的不知道为什么 thisUserController 中未定义。

任何帮助将不胜感激。

最佳答案

当你这样做时:

router.get('/users', userController.list);

传递给路由器的只是对 .list 方法的引用。 userController 实例丢失。这不是路由器独有的——这是事物如何在 Javascript 中传递的通用属性。为了进一步了解,您实际上在做的是:

let list = userController.list; 
// at this point the list variable has no connection at all to userController
router.get('/users', list);

而且,在 Javascript 的 strict 模式下,当你调用一个没有任何对象引用的常规函数​​时,例如调用上面的 list(),那么 this 将是函数内的 undefined。这就是您的示例中发生的情况。要修复它,您需要确保使用正确的对象引用调用您的方法,如 userController.list(...) 以便解释器设置 this适当的值(value)。

有多种方法可以解决这个问题:

制作自己的函数包装器

router.get('/users', function(req, res)  {
    userController.list(req, res);
});

这适用于任何版本的 Javascript。


使用 .bind() 为您制作一个使用正确对象调用它的包装器

router.get('/users', userController.list.bind(userController));

这适用于 ES5+ 或 .bind() polyfill。


使用 ES6 箭头函数快捷方式

router.get('/users', (...args) => userController.list(...args));

这适用于 ES6+


就我个人而言,我更喜欢 .bind() 实现,因为我认为它比其他任何实现都更简单、更具声明性/更清晰,而且 ES6“快捷方式”并不是真的更短。

关于javascript - 为什么在此类方法中未定义 "this"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45643005/

相关文章:

javascript - 如何通过单击一次销毁命名的 jquery-styles?

node.js - 当定义到 '/client' 的路线时,Railway.js + Jade 崩溃

javascript - Javascript 中变量不断变成对象而不是数组

c++ - 在静态成员方法中显式访问静态成员变量 - 在 C++ 中

javascript - 为什么 Chrome 在 TypeScript 中显示\ufeff 符号和灰线?

javascript - 如何在不删除选择框滚动条的情况下删除浏览器滚动条

javascript - Angular ng-repeat with 指令(在级联重复表中)

javascript - 点击 Facebook 中所有 "see more"的帖子

javascript - “this”关键字如何工作?

javascript - 在 module.exports 中调用函数的上下文安全方法是什么?