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

时间:2014-01-08 22:48:39

标签: javascript object callback

当我尝试使用回调函数中的“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");
    }
};

2 个答案:

答案 0 :(得分:4)

您需要在回调上使用.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 Documentation

  

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

垫片/填充物在这里:

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);

myfunc(param1, param2, param3)target作为this进行通话。

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

myfunc(param1, param2, param3)target作为this进行通话。

基本上区别在于.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.success(1,2,3,4)self称为this。如果您希望使用特定内容扩充参数,例如,如果您希望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);
}

答案 1 :(得分:1)

当您将该函数作为回调传递时,请执行以下操作:

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

.bind方法的调用将返回一个函数,该函数将确保调用您的“登录”函数,以便this引用“object_log”对象。

对于旧版浏览器at the MDN documentation site.

.bind有一个很好的垫片