无法获得范围外的功能

时间:2017-10-13 21:56:16

标签: javascript node.js

我正在尝试在MySQL查询中调用一个函数,但每次调用此函数时,我都会收到:this.test不是函数

query: function(db) {
    db.query("SELECT * FROM test", function(err, result, fields) {
        if (err) throw err;
        for (var r = 0; r < result.length; r++) {
           this.test();
        }
    });
},
test: function(){
  console.log("test");
}

我需要更改代码?

谢谢。

2 个答案:

答案 0 :(得分:2)

您需要在闭包中捕获this"that"模式通常用于此目的:

query: function(db) {
    var that = this;
    db.query("SELECT * FROM test", function(err, result, fields) {
        if (err) throw err;
        for (var r = 0; r < result.length; r++) {
           that.test();
        }
    });
},
test: function(){
  console.log("test");
}

正如其他人正确指出的那样,您也可以使用箭头功能。然后不需要that变量:

query: function(db) {
    db.query("SELECT * FROM test", (err, result, fields) => {
        if (err) throw err;
        for (var r = 0; r < result.length; r++) {
           this.test();
        }
    });
},

答案 1 :(得分:2)

在ES6(可在node.js中使用)中解决此问题的现代方法是使用回调的箭头函数定义来保留this的值。

query: function(db) {
    db.query("SELECT * FROM test", (err, result, fields) => {
        if (err) throw err;
        for (var r = 0; r < result.length; r++) {
           this.test();
        }
    });
},
test: function(){
  console.log("test");
}

默认情况下,任何函数调用都会根据函数的调用方式重置this的值。因此,当db.query()调用您的回调时,原始值this将丢失,并且在回调中不可用。使用ES6箭头语法声明这样的回调函数专门指示Javascript解释器在执行箭头函数声明的回调时保持this的词汇值(代码在此本地范围中具有的值)。

为了完整起见,有几种方法可以解决这个问题。

  1. 使用箭头函数声明回调而不是常规函数声明
  2. this的值保存到您可以引用的局部变量,而不是Igor的答案显示的this
  3. 在回调中使用.bind(this)强制回调this的值
  4. 创建this.test()的绑定版本,您可以在任何可以通过测试重新绑定this的地方调用,以便您可以调用它,甚至不在回调中使用this
  5. 在ES6之前,2和3是常见的解决方法。使用ES6,箭头功能通常是执行此操作的首选方式。

    另外,请认识到:

    if (err) throw err;
    

    在异步回调内部无效或有用的错误处理。要编写好的可靠代码,您需要编写真正的错误处理,并确定在发生此类错误时应用程序应该实际执行的操作。您还可能会发现,对所有异步操作使用promises可以更容易地将异步错误传播回更容易处理它们的位置。