【问题标题】:This scope lost with inheritance此范围因继承而丢失
【发布时间】:2013-09-24 19:11:50
【问题描述】:

这里是示例代码,两个文件和“类”。

具有已定义方法的 CRUD 类,this.modelName 出现问题,因为我设置了 this 上下文随此代码更改的路由:

问题是如何在定义模型名称的 CRUD 下获得相同的范围?

server.get('/users/:id', UserRoutes.find);

代码:

var db = require('../models');

function CRUD(modelName) {
    this.modelName = modelName;
    this.db = db;
}

CRUD.prototype = {

    ping: function (req, res, next) {
        res.json(200, { works: 1 });
    },

    list: function (req, res, next) {

        // FAILS BECAUSE the modelName is undefined
        console.log(this);

        db[this.modelName].findAll()
            .success(function (object) {
                res.json(200, object);
            })
            .fail(function (error) {
                res.json(500, { msg: error });
            });
    }
};

module.exports = CRUD;

UserRoutes 类:

var CRUD = require('../utils/CRUD'),
util = require('util');

var UserModel = function() {
    UserModel.super_.apply(this, arguments);
};

util.inherits(UserModel, CRUD);

var userRoutes = new UserModel('User');

module.exports = userRoutes;

【问题讨论】:

  • 问题是什么?
  • 我无法重现您的错误。 console.log(this); 按预期工作。为什么不呢?除非您使用 userRoutes.list 作为处理程序?
  • @freakish 我认为他的评论写错了,应该往下两行
  • @jcollum 是的,我已经意识到了,忘记删除评论了。 :)
  • 我希望 SO 对评论编辑/删除不是那么激进。

标签: javascript node.js oop


【解决方案1】:

我假设您在其他地方使用 userRoutes.list 作为处理程序,即上下文发生变化。在这种情况下,这应该是一个简单的解决方案:

function CRUD(modelName) {
    this.modelName = modelName;
    this.db = db;
    this.list = CRUD.prototype.list.bind(this);
}

请注意,您将无法使用该解决方案访问“另一个 this”(this 将永久绑定到 CRUD 实例,无论如何调用 .list)。

另一种选择是将list 转换为函数生成器(这与.bind 所做的几乎相同,只是您仍然可以在其他上下文中使用this):

CRUD.prototype = {
    // some code

    list: function() {
        var that = this;
        return function (req, res, next) {
            console.log(that);

            db[that.modelName].findAll()
                .success(function (object) {
                    res.json(200, object);
                })
                .fail(function (error) {
                    res.json(500, { msg: error });
                });
        }
    }
};

然后使用userRoutes.list() 作为处理程序。

【讨论】:

  • 目前最佳答案,因为解决方案适用于多个实例!
【解决方案2】:

这种事情通常通过将右侧的this 放入_this 来解决。在您的列表函数中,this 是函数对象,它没有模型名称对象。

var _this; 

function CRUD(modelName) {
    this.modelName = modelName;
    this.db = db;
    _this = this // <---------------
}

.... 
// call the _this in the outer scope 
db[_this.modelName]

【讨论】:

  • 通过为旧范围声明变量来冻结范围的好答案似乎是有效的,并且在这种情况下是唯一的解决方案。
  • 是的,如果您假设没有其他 CRUD 实例,这是一个很好的答案。
  • @freakish 是一种反手的恭维;还是被动的攻击性刺拳?
  • @jcollum 我不是故意冒犯你的。这确实是一个很好的答案。毕竟有单身人士。
  • @freakish 抱歉,我认为这意味着我在 reddit 上花费了太多时间
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多