Reputation: 1320
I have been reading up on the intricacies of 'this' in JavaScript. Given this code:
$(document).ready(function() {
console.dir(this);
(function foo() {
console.dir(this);
})();
});
In Chrome, the console shows the first 'this' as an 'HTMLDocument' (as I expected), but the second 'this' is 'undefined'. Can someone point me to a good explanation of why?
Upvotes: 2
Views: 92
Reputation: 754515
They way in which a javascript function is invoked changes the meaning of this
inside of it. Here you've invoked a method which isn't associated with any object hence it has no this
value to bind to.
In the first case the callback is being invoked via JQuery and they are manipulating the callback such that this
points to the document
DOM element. It's easy to visualize this as your callback being invoked with apply
yourCallback.apply(document, null);
You can fix the second version like so
$(document).ready(function() {
console.dir(this);
var that = this;
(function foo() {
console.dir(that);
})();
});
Or another way using apply
$(document).ready(function() {
console.dir(this);
(function foo() {
console.dir(this);
}).apply(this, null);
});
Upvotes: 3
Reputation: 63802
If that code is put into the console of a page with jQuery loaded, the second "this" is DOMWindow, which is the global "this". It is not undefined.
There must be something else on your page.
Upvotes: 1
Reputation: 42158
The second this
is in an anonymous function which has no context. this
is always an implicit variable at the function level, so your inner functions this
is shadowing the outer this
Upvotes: 0
Reputation: 99879
this
is the context with which the current function has been called.
object
become the context.jQuery calls your ready function with document
as the context. And you call your immediately executed function without context, which is why it's null.
You can do this:
// assign `this` to that so you can access `this` through `that`
var that = this;
(function foo() {
console.log(that);
}());
Or this:
// bind the function to `this` and then call it
$.proxy(function() {
console.log(this);
}, this)();
See jQuery.proxy
.
Or even this:
// call the function with `this` as context
(function() {
console.log(this);
}).call(this);
See Function.call
.
Upvotes: 1