[英]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.