簡體   English   中英

Javascript回調的范圍問題

[英]Scoping problem with Javascript callback

我在使回調函數工作時遇到了一些麻煩。 這是我的代碼:

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',但是,我無法讓它工作。

如果有人能告訴我我應該做什么,我會非常感激。 我仍然圍繞着閉包的工作方式,特別是它們如何在這種情況下工作。

謝謝!

那么最直接的事情是將“this.readSuccess”包裝在另一個函數中:

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

一些Javascript框架提供了一個實用程序來將一個函數“綁定”到一個對象,這只是意味着它為你創建了一個小函數。 請注意,變量“obj”將由那些小函數“記住”,因此當調用處理程序時,“this”引用將是用於調用“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”其實呢,這是很難知道是否值this實際上是失去了,如果var obj = this實際需要。 有可能它不是,所以你可以使用這種代碼:

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框架提供了一個bind函數來簡化這類問題。 但是你不需要一個完整的框架:這是一個非常好的Function#bind方法,可以使用普通的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));
    };
}

Function#bind的幫助下,您可以編寫:

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

以下網站似乎表明問題可能在您的“班級”建築中比在使用中更多。 如果你讀到“使用原型屬性重寫”,他們會寫出“類”結構的特定方法將使方法保持全局而不是基於實例。 也許另一種創作方法?

http://devedge-temp.mozilla.org/viewsource/2001/oop-javascript/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM