简体   繁体   中英

Passing method name as a callback VS. wrapping it with annoymous function

I have a button #test.

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

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

This will log an empty string (logging typeof this.name gives a string).

Edit: I understand this context becomes the button, hence this.name returns nothing.

Versus

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

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

What is the difference?

Edit: How does wrapping obj.test() with an annon function make it behave differently than above?

The real difference is what object test is operating on. When you call the function in the second example you are calling the function with the obj context. In the first example you are passing a reference to the function but not the context that it was attached to. In the first case when the function is called it is actually operating the the global scope.

To test this out try putting: var name = "eiriki"; somewhere in global scope then running your function. It will likely print out eiriki unless you have something else assigning to it already.

It's about resolving this . If you use $("#test").on("click", obj.test); then this will be the button but if you pass a closure then this will be obj .

When I call obj.test then this in test will be obj.

JQuery will set this to be the button when it's clicked so passing obj.test without a reference to obj being this will break your obj.test function.

The best way to resolve this problem is to use Function.prototype.bind (you need the polyfil for IE < 9):

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM