在javascript中传递包括其上下文的函数

时间:2013-07-08 00:37:13

标签: javascript

在javascript中有一些我不理解的东西,并将样本问题分解为一个基本案例:

    a = function () {
      this.b = 5;
    }

    a.prototype.c = function () {
      alert(this.b);
    }

    var d = new a();
    var e = d.c; // how do I save a ref to the method including the context (object)??

    d.c(); // 5 -> ok
    e();   // undefined -> wtf??

那么为什么在上一个例子中没有上下文调用函数呢?我怎样才能用上下文来调用它?

提前致谢: - )

3 个答案:

答案 0 :(得分:5)

d.c就像一个未绑定的实例方法。您可以使用Function.prototype.bind创建一个绑定到d的新函数(.bind的第一个参数是this参数):

var e = d.c.bind(d);

或使用e作为d参数调用this

e.call(d);

答案 1 :(得分:2)

您需要使用该对象调用该方法以获得正确的上下文。所以:

var e = function() { return d.c(); };

在较新的浏览器中,您可以使用bind method执行相同的操作:

var e = d.c.bind(d);

例如,在jQuery中,您可以在旧版浏览器中使用proxy method

var e = $.proxy(d.c, d);

答案 2 :(得分:1)

这是关于解析this值。这可以通过以下方式解决:

myObject.something();//this in something is myObject
window.something();//this is window
button.onClick=function();//this when button is clicked is button

如何解决它已经给出了,如下例中使用setTimeout

传递回调是一个常见的陷阱
var test = function () {
  var me = this;// set reference to this
  this.sayAgain=function(){
     console.log("Hi, I am "+me.toString());
  }
}
test.prototype.toString=function(){
   return "test";
}

test.prototype.say = function () {
  console.log("Hi, I am "+this.toString());
}

var t = new test();
setTimeout(t.say,50);//=window passing functon without ref to this
setTimeout(function(){
  t.say();
},150);//=test passing ref with function
setTimeout(t.sayAgain,200);//=test using me as the saved this context

第二次超时将closure传递给setTimeout,如果你计划传递数百次回调,但只创建几个测试对象实例,那么最后一次执行(sayAgain)会执行稍好一点。

这是因为你在创建测试实例时创建了一个闭包,但是在将sayAgain作为回调传递时没有创建一个闭包,如果你创建了很多测试实例并且多次没有传递say那么就删除this.me和this。 sayAgain从函数体中传递say作为闭包。

您可以使用Function.prototype.bind,但在IE<< 8,我不确定它是否会在我的示例中使用t.say创建一个闭包。