0

this inside a closure. It is important to take note that closures cannot access the outer function’s this variable by using the this keyword because the this variable is accessible only by the function itself, not by inner functions.

For example:

var user = {
tournament:"The Masters",
data      :[
{name:"T. Woods", age:37},
{name:"P. Mickelson", age:43}
],

clickHandler:function () {
// the use of this.data here is fine, because "this" refers to the user object, and data is a property on the user object.

this.data.forEach (function (person) {
// But here inside the anonymous function (that we pass to the forEach method), "this" no longer refers to the user object.
// This inner function cannot access the outer function's "this"

console.log ("What is This referring to? " + this); //[object Window]

console.log (person.name + " is playing at " + this.tournament);
// T. Woods is playing at undefined
// P. Mickelson is playing at undefined
})
}

}

user.clickHandler(); // What is This referring to? [object Window]

My question is: Why is this of some function below referring to jquery's button object instead of the window Object. Afterall, the callback function (some function) is still inside another function (click).

$("button").click (some function);

Also, I took a look at another similar question on SO but I am still none the wiser. "this" keyword inside closure

Community
  • 1
  • 1
Tomatoes
  • 91
  • 1
  • 7

2 Answers2

6

My question is: Why is this of some function below referring to jquery's button object instead of the window Object.

Because jQuery calls the handler setting the meaning of this explicitly, via the Function#call function (or it could be Function#apply, I'd have to look at the jQuery source).

Here's a simple example of using call:

function foo() {
    console.log("this.answer = " + this.answer);
}

var obj = {answer: "42"};
foo.call(obj); // The first argument is used as `this` during the call

That will output

this.answer = 42
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • so, basically we keep using call or apply until we set the "this" to refer to what we want it to refer to. ie, $("button").click (object.somefunction.call(obj)) Right? – Tomatoes Nov 27 '13 at 12:30
  • @Tomatoes: No, that code would *call* `object.somefunction` immediately and pass its *result* into `$("#button").click()`. What I'm saying is that `this` refers to the DOM element (not a jQuery object) within the `click` callback because jQuery ensures that it does, intentionally. Internally, jQuery does that by calling your handler via `call` (or `apply`). – T.J. Crowder Nov 27 '13 at 12:38
  • I was trying to set `this` to `obj` in `object.somefunction.call(obj))` but am derailing the discussion with that. I know that $(this) refers to jquery object and `this` falls back to the javascript `this`. But thought `this` in that callback function within click referred to $("button") jquery object, since usually `this` refer to the object initiating the function containing the `this`. – Tomatoes Nov 27 '13 at 13:08
  • so from what u have said, `this` within that callback function within click SHOULD refer to the initiating object, $("button") jquery object, but jquery makes it intentioally refer to the DOM element (window object)? – Tomatoes Nov 27 '13 at 13:17
  • @Tomatoes: No, there's nothing intrinsic about passing a callback into a function that defines in any way what `this` will be when the callback is called. That's entirely defined by the API you're passing the callback into. *(Re your email: Yes, SO notifies people of replies.)* – T.J. Crowder Nov 27 '13 at 13:41
  • In that case, the info on the article below is wrong. Specifically check point 1. Fix `this` when used in a method passed as a callback http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/ – Tomatoes Nov 27 '13 at 13:45
  • Also, it's not about the callback function. The value `this` is assigned is based exclusively on the object that invokes the `this Function`. `this` has the value of the invoking object. So in this case, just as an example, jquery button object is the invoking object. So `this` SHOULD refer to the button object (unless of course like u said, jquery intentionally points it to something else). Nothing intrinsic about the calling function BUT that is how `this` works - by refering to the invoking object NOT the defining object. – Tomatoes Nov 27 '13 at 14:01
  • @Tomatoes: You're confusing the call **to** `click` with the call that later gets made to the function you pass *into* `click`. During the call *to* `click` (e.g., `$("#button").click(...)`), within the code of the `click` function, `this` is indeed the jQuery object on which you called it. Which has absolutely nothing to do with what `this` might be later when the function you're passing into it gets called. – T.J. Crowder Nov 27 '13 at 14:07
  • So is the following correct? During call **to** click, a javascript `this` within click function itself (not other functions inside click) refers to button jquery object (since that is the invoking object). Another javascript `this` within a function within click refers to the DOM object (in non-strict mode). – Tomatoes Nov 27 '13 at 14:15
  • @Tomatoes: Whether a function is "in" another function is completely irrelevant to the value of `this`. The callback you pass into `click` is not "in" the `click` function. The only reason that `this` is the DOM element in the **call to** your handler function is that jQuery intentionally makes that true when calling it. More on my blog: [*Mythical methods*](http://blog.niftysnippets.org/2008/03/mythical-methods.html) and [*You must remember `this`*](http://blog.niftysnippets.org/2008/04/you-must-remember-this.html) – T.J. Crowder Nov 27 '13 at 14:20
  • I will take a look at your articles. Btw if we forget about jquery for a second and just think in terms of a generic object and the DOM object, the author states that "It is important to take note that closures cannot access the outer function’s this variable by using the this keyword because the this variable is accessible only by the function itself, not by inner functions" so in non-strict mode according to the author, `this` in "inner" functions point to the DOM object (window object). – Tomatoes Nov 27 '13 at 14:25
  • So `this` within that callback function within click, either points to the invoking object (jquery in this instance but could be just any object) or to the DOM object. Its one or the other. If i know which it is , I think I will have my answer – Tomatoes Nov 27 '13 at 14:27
  • "Whether a function is "in" another function is completely irrelevant to the value of this". With all due respect, I, and think the author I refered to above, will disagree with this statement. Afterall he goes to great lengths to explain why to "fix" `this` inside closures and callback functions. – Tomatoes Nov 27 '13 at 14:33
  • @Tomatoes: Right, but it has nothing to do with where the function is, and everything to do with ***how the function is called***. Containment is irrelevant to the value `this` has within a function. Full stop. Containment sometimes relates to what you do when `this` isn't what you want, but not to what `this` is. – T.J. Crowder Nov 27 '13 at 15:30
  • thanks for all the help. i may have finally figured it out. http://jsfiddle.net/EqHJ7/ – Tomatoes Nov 27 '13 at 17:30
1

You have it right that the 'this' keyword which refers to the object on which the currently executing method has been invoked. So in your first example the clickHandler() function is going to refer to the user object.

Now in terms of jQuery when you are inside of a callback function 'this' is referring to the the 'DOM' element. The reason for this as i understand is that jQuery returns a object from its internal 'jQuery' code that maintains the reference to the element that was in context being the 'DOM' element using call() and apply(). I believe to maintain it. Doing so also allows you to accomplish that chaining of actions like ("button").click(somefunction).fadeIn() for example.

If you make your own jquery function such as $.fn.somefunction = function() {...} this refers to a jQuery object at this point.

There might be a better why to accomplish this but I quickly changed your code using call() to make is refer to your user object.

var user = {
    tournament:"The Masters",
    data      :[
        {name:"T. Woods", age:37},
        {name:"P. Mickelson", age:43}
    ],

    clickHandler: function () {
    // the use of this.data here is fine, because "this" refers to the user object, 
    // and data is a property on the user object.

    this.data.forEach (function (person) {
        // But here inside the anonymous function (that we pass to the forEach method),
        //"this" no longer refers to the user object.
        // This inner function cannot access the outer function's "this"

        //Use call to make this refer to your user object
        that = Object.call(this, user);

         console.log ("What is This referring to? " + that); //[object Object]

         console.log (person.name + " is playing at " + that.tournament);
         // T. Woods is playing at undefined
         // P. Mickelson is playing at undefined
        })
     }

    }

user.clickHandler(); // What is This referring to? [object Object]

Another thing is in Javascript the forEach function takes a second parameter that will be used as the object to reference for 'this' so another way you could have done it. Now this refers to user object.

....

this.data.forEach (function (person) {
    // But here inside the anonymous function (that we pass to the forEach method),
    //"this" no longer refers to the user object.
    // This inner function cannot access the outer function's "this"

    //Use call to make this refer to your user object

     console.log ("What is This referring to? " + this); //[object Object]

     console.log (person.name + " is playing at " + this.tournament);
     // T. Woods is playing at Masters
     // P. Mickelson is playing at Masters
     //pass user as the object the second parameter
    }, user)
 }

}

Check out the explanation of this on the jquery site here is a link.

http://learn.jquery.com/javascript-101/this-keyword/

elrick
  • 681
  • 4
  • 5