javascript:从回调函数调用对象内部的函数



当我试图从回调函数中使用"this"调用对象内部的函数时,会出现一个错误,表示该方法未定义。我该如何解决这个问题!。

var object_log = {
user: "",
pass: "",
error_message: "an error occured while connecting",
init: function(user, pass) {
this.user = user;
this.pass = pass;
},
login: function() {
remote_submit(identify, this.success, this.error);
},
error: function() {
alert(this.error_message);
},
success: function() {
alert("success");
}
};

您需要在回调中使用.call().apply()方法来指定调用该方法的上下文。

回调方法remote_submit不知道this将是什么,因此当它调用回调方法时,它们就像不在对象上的普通函数一样执行。

您可以通过在退出时包装函数来"绑定"它们:

var self = this;
remote_submit(
identify,
function() { return self.success.apply(self, arguments); },
function() { return self.error.apply(self, arguments); }
);

这允许您在匿名函数的闭包中传递上下文,并使用独占的this上下文执行回调。

在EMCAScript5+中,您可以在函数上使用bind来绑定它以在回调中使用:

remote_submit(identify, this.success.bind(), this.error.bind())

但是,从MDN文档来看:

bind函数是ECMA-262第5版的最新添加;因此,它可能不存在于所有浏览器中。您可以通过在脚本的开头插入以下代码来部分解决此问题,从而允许在本机不支持bind()的实现中使用bind(()的大部分功能

垫片/polyfill在这里:

if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1), 
fToBind = this, 
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}

更新

为了回答您的其他问题,让我们首先查看callapply文档,并分解它们的工作方式:

从根本上说,他们的工作原理是一样的,唯一的区别是他们如何看待自己的论点:

myfunc.call(target, param1, param2, param3);

将以target作为this调用myfunc(param1, param2, param3)

var args = [param1, param2, param3];
myfunc.apply(target, args);

将以target作为this调用myfunc(param1, param2, param3)

基本上的区别在于.apply()采用了一个参数数组,其中call函数要求您在代码中写入参数。

接下来,如果我们看看我给你的例子:

function() { return self.success.apply(self, arguments); }

这将返回一个函数,该函数将通过将传递给匿名函数的所有参数(arguments变量)传递给apply函数来调用回调。因此:

var a = function() { return self.success.apply(self, arguments); };
a(1,2,3,4);

这将使用self作为this来调用self.success(1,2,3,4)。如果你想用一些特定的东西来扩充参数,例如,如果你想让a(1,2,3,4)调用self.success(self.test, 1, 2, 3, 4),那么你必须为apply函数提供一个扩充的数组:

var a = function() {
var args = [self.test];
for(var i = 0; i < arguments.length; i++) args[] = arguments[i];
return self.success.apply(self, args);
}

当您将函数作为回调传递时,如下所示:

whatever( object_log.login.bind( object_log ) );

.bind方法的调用将返回一个函数,该函数将确保您的"login"函数将被调用,以便this引用"object_log"对象。

MDN文档站点上有一个适用于旧浏览器的.bind的良好填充程序。

最新更新