Reputation: 1591
What is the difference between the following two statements (in the context of the global window)?
(function() { return a; } )(); // ReferenceError: a is not defined
(function(a) { return a; } )(); // returns undefined
I assume it has something to do with the following:
a; // ReferenceError: a is not defined
window.a; // undefined
It seems the second function goes up the scope chain and ends at the global window scope, where a
is not a property of window and thus returns undefined
. But shouldn't the first function also do the same and return undefined
as well?
I found this SO question about undefined vs. not defined, but it seems to apply more relating to variables and not about properties in the window scope.
Upvotes: 1
Views: 1385
Reputation: 276306
I think that this is a common pitfall and an important question, if you're reading this and anything is unclear please let me know in the comments.
a;
- will throw a reference error because it's trying to access an undefined variable
function() { return a; } )();
- this is exactly like the case above, it's an access to an undefined variable
object.a
- will return undefined, we're not trying to access an undefined variable here, but rather the property of a known object, this is different
(function(a) { return a; } )();
- will return undefined, a
is a parameter here and not an undefined variable, it will be assigned the actual language primitive value type undefined
.
Let's dig a little bit deeper shall we?
Let's see what the language specification has to say about all these cases:
The spec states here:
If IsUnresolvableReference(V), throw a ReferenceError exception.
The spec states:
IsUnresolvableReference(V). Returns true if the base value is undefined and false otherwise.
This is why the following happens:
a; // ReferenceError: a is not defined
Since the base value is not defined, it throws a reference error as the spec specifies.
In an object, base is not undefined (it's the object) so it's all good and no error is thrown. It is resolved as such:
The following [[Get]] internal method is used by GetValue when V is a property reference with a primitive base value. It is called using base as its this value and with property P as its argument. The following steps are taken:
Let O be ToObject(base).
Let desc be the result of calling the [[GetProperty]] internal method of O with property name P.
If desc is undefined, return undefined.
Which, is why you see:
window.a; // undefined
The other case - parameter is completely different, the parameter exists, but its value is set to the primitive value type undefined. There is a difference between existing and being undefined and not existing :)
This is specified here:
If n is greater than argCount, let v be undefined otherwise let v be the value of the n’th element of args.
Which is why:
(function(a) { return a; } )(); // returns undefined
Upvotes: 6
Reputation: 239301
You're really over-thinking your second case: (function(a) { return a; } )(); // returns undefined
Yes, but it has nothing to do with this:
... goes up the scope chain and ends at the global window scope, where a is not a property of window and thus returns undefined
You defined a parameter for the function, named a
. Because you didn't supply a value, it is undefined
. It's really that simple.
Upvotes: 1