我在使用回调函数时遇到了一些麻烦。这是我的代码:
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',但是,我无法让它工作。
如果有人能告诉我我应该做什么,我会非常感激。我仍然围绕着闭包的工作方式,特别是它们如何在这种情况下工作。
谢谢!
答案 0 :(得分:2)
最直接的做法是将“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”的对象。
答案 1 :(得分:2)
这里的问题不是完全关闭或作用域问题。问题是,当您将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)
);
}
答案 2 :(得分:0)
以下网站似乎表明问题可能在您的“班级”建筑中比在使用中更多。如果你读到“使用原型属性重写”,他们会写出“类”结构的特定方法将使方法保持全局而不是基于实例。也许是另一种创作方法?
http://devedge-temp.mozilla.org/viewsource/2001/oop-javascript/