Javascript回调的作用域问题

Javascript回调的作用域问题,javascript,callback,closures,this,Javascript,Callback,Closures,This,我在使用回调函数时遇到了一些问题。这是我的密码: SomeObject.prototype.refreshData = function() { var read_obj = new SomeAjaxCall("read_some_data", { }, this.readSuccess, this.readFail); } SomeObject.prototype.readSuccess = function(response) { this.data = response;

我在使用回调函数时遇到了一些问题。这是我的密码:

SomeObject.prototype.refreshData = function()
{
  var read_obj = new SomeAjaxCall("read_some_data", { }, this.readSuccess, this.readFail);
}

SomeObject.prototype.readSuccess = function(response)
{
    this.data = response;
    this.someList = [];
    for (var i = 0; i < this.data.length; i++)
    {
      var systemData = this.data[i];
      var system = new SomeSystem(systemData);
      this.someList.push(system);
    }
    this.refreshList();
}
基本上,SomeAjaxCall是对数据发出ajax请求。如果成功,我们使用回调“this.readSuccess”,如果失败,则使用回调“this.readFail”

我发现SomeObject.readSuccess中的“this”是全局的,也就是窗口对象,因为我的回调是作为函数而不是成员方法调用的。我的理解是,我需要使用闭包来保持“this”的存在,但是,我一直无法让它工作

如果有人能告诉我应该做什么,我会非常感激。我仍然在思考闭包是如何工作的,特别是在这种情况下它们是如何工作的


谢谢

最简单的方法是将此函数包装到另一个函数中:

SomeObject.prototype.refreshData = function()
{
  var obj = this;
  var read_obj = new SomeAjaxCall("read_some_data", { }, 
    function() { obj.readSuccess(); }, function() { obj.readFail(); });
}

一些Javascript框架提供了一个将函数绑定到对象的实用程序,这意味着它可以为您创建一个小函数。请注意,这些小函数将记住变量obj,因此,当调用处理程序时,此引用将指向用于调用refreshData的对象。

最简单的方法是将其包装到另一个函数中。readSuccess:

SomeObject.prototype.refreshData = function()
{
  var obj = this;
  var read_obj = new SomeAjaxCall("read_some_data", { }, 
    function() { obj.readSuccess(); }, function() { obj.readFail(); });
}

一些Javascript框架提供了一个将函数绑定到对象的实用程序,这意味着它可以为您创建一个小函数。请注意,这些小函数将记住变量obj,因此当调用处理程序时,此引用将指向用于调用refreshData的对象。

以下站点似乎表明,问题可能更多地出现在类构建中,而不是在使用中。如果你仔细阅读使用原型属性的重写,他们会写道,特定的类结构方法将保持方法的全局性,而不是基于实例的。也许是另一种创作方法


下面的网站似乎表明,问题可能更多地出现在你的班级建设中,而不是在使用中。如果你仔细阅读使用原型属性的重写,他们会写道,特定的类结构方法将保持方法的全局性,而不是基于实例的。也许是另一种创作方法

这里的问题并不完全是闭包或范围问题。问题是,当您将this.readSuccess分配给变量时,您分配的函数本身并不知道它原来所属的对象

同样,您可以采用常规的独立函数,并将其用作对象的方法:

function hello() {
    alert("Hello "+this.planet);
}
var planet = "Earth";
hello(); // -> 'Hello Earth'

var Venus = {
    planet: "Venus"
};
hello.apply(Venus); // -> 'Hello Venus'
Venus.hello = hello;
Venus.hello(); // -> 'Hello Venus'
在本例中,您的问题可以重复

var helloVenus = Venus.hello;
helloVenus(); // -> 'Hello Earth'
因此,您的问题是将this.readSuccess分配给某个变量,并将其作为此方法调用。这可以通过Pointy演示的闭包来完成。因为我不知道SomeAjaxCall实际上做了什么,所以很难知道这个值是否真的丢失了,以及var obj=这个值是否真的需要。很可能不是这样,所以您可以使用这种代码:

var helloVenus = function() { Venus.hello() }
helloVenus(); // -> 'Hello Venus'
在您的情况下,这将是编辑:添加传递给处理程序的参数:

SomeObject.prototype.refreshData = function()
{
  var read_obj = new SomeAjaxCall(
    "read_some_data",
    { },
    function () { this.readSuccess.apply(this, arguments) },
    function () { this.readFail.apply(this, arguments) }
  );
}
如前所述,一些js框架提供了一个绑定函数来简化此类问题。但你不需要一个完整的框架来实现这一点:这里有一个完美的Functionbind方法,可用于普通javascript:

Function.prototype.bind = function(obj) {
    var __method = this;
    var args = [];
    for(var i=1; i<arguments.length; i++)
        args.push(arguments[i]);
    return function() {
        var args2 = [];
        for(var i=0; i<arguments.length; i++)
            args2.push(arguments[i]);
        return __method.apply(obj, args.concat(args2));
    };
}
这里的问题并不完全是闭包或范围问题。问题是,当您将this.readSuccess分配给变量时,您分配的函数本身并不知道它原来所属的对象

同样,您可以采用常规的独立函数,并将其用作对象的方法:

function hello() {
    alert("Hello "+this.planet);
}
var planet = "Earth";
hello(); // -> 'Hello Earth'

var Venus = {
    planet: "Venus"
};
hello.apply(Venus); // -> 'Hello Venus'
Venus.hello = hello;
Venus.hello(); // -> 'Hello Venus'
在本例中,您的问题可以重复

var helloVenus = Venus.hello;
helloVenus(); // -> 'Hello Earth'
因此,您的问题是将this.readSuccess分配给某个变量,并将其作为此方法调用。这可以通过Pointy演示的闭包来完成。因为我不知道SomeAjaxCall实际上做了什么,所以很难知道这个值是否真的丢失了,以及var obj=这个值是否真的需要。很可能不是这样,所以您可以使用这种代码:

var helloVenus = function() { Venus.hello() }
helloVenus(); // -> 'Hello Venus'
在您的情况下,这将是编辑:添加传递给处理程序的参数:

SomeObject.prototype.refreshData = function()
{
  var read_obj = new SomeAjaxCall(
    "read_some_data",
    { },
    function () { this.readSuccess.apply(this, arguments) },
    function () { this.readFail.apply(this, arguments) }
  );
}
如前所述,一些js框架提供了一个绑定函数来简化此类问题。但你不需要一个完整的框架来实现这一点:这里有一个完美的Functionbind方法,可用于普通javascript:

Function.prototype.bind = function(obj) {
    var __method = this;
    var args = [];
    for(var i=1; i<arguments.length; i++)
        args.push(arguments[i]);
    return function() {
        var args2 = [];
        for(var i=0; i<arguments.length; i++)
            args2.push(arguments[i]);
        return __method.apply(obj, args.concat(args2));
    };
}

实际上,这里发生的情况是,obj被锁定在计算函数{obj.readSuccess;}时创建的闭包中。除非使用Prototype或jQuery之类的库,否则没有其他方法可以做到这一点;它们有一个.bind函数,可以透明地创建闭包。不是吹毛求疵,而是为了StackOverflow后代的利益,jQuery版本被称为代理,而不是绑定。这非常有意义。jQuery代理函数可以工作,这就是g
reat。然而,为了完整性,我仍然有点困惑,如果我不使用jQuery,我将如何处理这个问题。在我的示例中,readSuccess有一个参数response,它将在以后填充。所以说函数{obj.readSuccesswah;}对我来说没有意义,因为wah??应该在以后的时间通过。我尝试了函数{obj.readSuccess;},但没有成功。有什么想法吗?你完全正确,纳兹伯特。我们不应该假设readSuccess是无条件调用的,因为事实可能并非如此。请参阅我的答案以获得解决方案。实际上,这里发生的情况是,在计算函数{obj.readSuccess;}时,obj被锁定在创建的闭包中。除非使用Prototype或jQuery之类的库,否则没有其他方法可以做到这一点;它们有一个.bind函数,可以透明地创建闭包。不是吹毛求疵,而是为了StackOverflow后代的利益,jQuery版本被称为代理,而不是绑定。这非常有意义。jQuery代理函数可以工作,这很好。然而,为了完整性,我仍然有点困惑,如果我不使用jQuery,我将如何处理这个问题。在我的示例中,readSuccess有一个参数response,它将在以后填充。所以说函数{obj.readSuccesswah;}对我来说没有意义,因为wah??应该在以后的时间通过。我尝试了函数{obj.readSuccess;},但没有成功。有什么想法吗?你完全正确,纳兹伯特。我们不应该假设readSuccess是无条件调用的,因为事实可能并非如此。看看我的答案,这是一个很好的答案。非常感谢您提供的信息。现在bind是ECMAScript 5的一部分:这是一个很好的答案。非常感谢您提供的信息。现在,bind是ECMAScript 5的一部分: