When you invoke a top-level function in Javascript, the this keyword inside the function refers to the default object (window if in a browser). My understanding is that
You can call any function that is in scope with functionName()
. Since you haven't called it on an object, it will be called in the context of the default object (window
). (IIRC, it will be called in the context of undefined
if you are in strict mode).
The default object for context has nothing to do with where a function is defined or what scope that function appears in. It is simply the default object.
If a function is a property of an object, you can call it as reference.to.object.function()
, and it will be called in the context of object
instead of the default object.
Other things that change the context are the new
keyword and the apply
, call
, and bind
methods.
It does not depend where the function is declared but how it is called:
var obj = {
f: function() {
return this;
}
}
var f = obj.f;
console.log(obj.f()) // obj
console.log(f()) // window/default obj
Or in other words. The syntax obj.f()
executes the function with this=obj
while f()
executes the function with this=window
. In JavaScript the caller specifies the value of this
.
Whether a function is nested inside another one has nothing to do with the value of this
when the function is called. The only things that matter are:
If the function is "found" by traversing a property on an object, then the value of this
will be a reference to that object:
someObject.prop( whatever );
It doesn't matter how the function was declared.
If you use call()
or apply()
to invoke a function, then the value of this
is taken from the first argument to whichever of those functions you use.
If you've created a bound wrapper for the function with bind()
, then the value of this
will be as requested when bind()
was called.
If you're calling a function as a constructor with new
, then this
will refer to the newly-created object instance.
Otherwise, this
is either a reference to the global context, or else it's undefined
(in "strict" mode or in an ES5-compliant runtime).
The "location" in the code where a function is defined does matter, of course, in that the scope includes whatever symbols it includes, and those are available to the function regardless of how a reference to it is obtained.
In JavaScript, when a function is invoked without an explicit context, the context is the global object. In the case of web browsers, the global object is window
.
Additionally, JavaScript has functional scope, so any variables or functions within a function are not accessible in a scope outside of that function. This is why you can't access window.innerFunc
.
When you define func
in the global scope, it actually is assigned as a property of the window
object. That is, the window
object holds all globally scoped variables. (*) Therefore, func
and window.func
represent the same thing. innerFunc
is defined inside a function scope and is not available outside of that scope. Therefore, window.innerFunc
is (still) undefined
.
However, the this
context is determined by how you call the function. When you call a method like obj.method()
, the this
context is set to obj
. On the other hand, you can also call the method on its own:
var f = obj.func;
f(); // in this call: this === window
In this case, you're not calling a function on an object and thus the this
context is set to the default. The default however is the global scope and as stated above, this is represented by window
.
You can always override the this
context by using Function.prototype.call()
or Function.prototype.apply()
which take a this
context as first argument. For example:
var f = obj.func;
f.call(obj); // in this call: this == obj
(*) Note that this only applies to JavaScript running inside a browser. In other environments, this may differ. For example, in Node.js the GLOBAL
variable holds the global scope.