传递方法名称作为回调VS.用匿名函数包装它

时间:2013-07-09 01:11:43

标签: javascript callback

我有一个按钮#test。

var obj = {
  name: "John",
  test: function() {
    console.log('name '+ this.name );
  }
};

$("#test").on( "click", obj.test);

这将记录一个空字符串(记录typeof this.name给出一个字符串)。

编辑:我理解上下文成为按钮,因此this.name不返回任何内容。

对战

var obj = {
  name: "John",
  test: function() {
    console.log('name '+ this.name );
  }
};

$("#test").on( "click", function() {
  obj.test();  //logs John
});

有什么区别?

编辑:如何用一个annon函数包装obj.test()使它的行为与上面不同?

2 个答案:

答案 0 :(得分:1)

真正的区别在于对象测试的作用。当您在第二个示例中调用该函数时,您正在使用obj上下文调用该函数。在第一个示例中,您将传递对函数的引用,但不传递它附加到的上下文。在调用函数的第一种情况下,它实际上是在操作全局范围。

要测试这个,请尝试: var name =“eiriki”;在全球范围内的某个地方然后运行您的功能。它可能会打印掉eiriki,除非你已经分配了其他内容。

答案 1 :(得分:1)

关于解决this的问题。如果您使用$("#test").on("click", obj.test);,则this将成为按钮,但如果您传递closure,那么this将为obj

当我调用obj.test时,测试中的this将是obj。

JQuery会在点击时将this设置为按钮,这样在没有引用obj为this的情况下传递obj.test会破坏你的obj.test函数。

解决此问题的最佳方法是使用Function.prototype.bind(对于IE< 9),您需要polyfil

var obj = {
    name: "John",
    test: function () {
        console.log('This is:' + this.toString());
    },
    toString: function () {
        return "It's test"
    }
};

$("#test").on("click", function () {
    // by the way; this here is the button
    console.log("what's this here:", this.toString());
    obj.test();  //works but creates a closure
});

$("#test").on("click", obj.test);//breaks, this will be button in test

$("#test").on("click", obj.test.bind(obj));//works

// now to show how this is resolved
window.mytest = obj.test;
window.mytest();// this is window
var obj2 = {
    toString: function () {
        return "this is obj2";
    }
};
obj2.test = obj.test;
obj2.test();//this is obj2