javascript named function expressions - scope accessibility [duplicate]
I'm following John Resig's Secrets of JS ninja slides and I've found something I don't clearly understand. Following code defines a named function expression:
var ninja = function myNinja(){
console.log(myNinja); // function myNinja() {...}
};
myNinja; // undefined
As I can see, in the current scope (suppose it's global), ninja
is the variable that holds reference to the named function myNinja
. ninja
variable is accessible in the scope - that's clear, but myNinja
is not accessible in the scope (but it's accessible inside its own function). How come?
If I define a function (not using a function expression, but function declaration):
function Cheese() {
console.log(Cheese);
}
then it's accessible in the current scope. I know that this just works like that - but can someone explain why is that?
In his book, The Secrets of the JavaScript Ninja, John Resig makes a wonderful explanation about this concept.
http://jsninja.com/
Below are the quotes from the book:
4.2.4. Inline named functions
<script type="text/javascript">
var ninja = function myNinja(){
assert(ninja == myNinja, "this is named two things at once!");
};
ninja();
assert(typeof myNinja == "undefined",
"But myNinja isn't defined outside of the function.");
</script>
This listing brings up the most important point regarding inline functions: even though inline functions can be named, those names are only visible within the functions themselves.
Remember the scoping rules we talked about back in chapter 3? Inline function names act somewhat like variable names, and their scope is limited to the function within which they’re declared.
3.2.1. Scoping and functions
Variable declarations are in scope from their point of declaration to the end of the function within which they’re declared, regardless of block nesting.
If you would like to know more about this concept, this book will help you.
why is that?
A function expression creates a new function object every time it is evaluated. What happens with that result is irrelevant at first. But…
var ninja;
// myNinja; - what would you expect it to be here?
for (var i=0; i<5; i++)
ninja = function myNinja(){
console.log(myNinja);
};
// myNinja; - *which one* would you expect it to be here?
ninja();
The call to ninja()
is obvious, it references the function that was assigned to that variable at last. And the myNinja
in the console.log
references the current function object - it's in its own scope.
But the myNinja
identifier would be ambiguous outside the function itself.
In contrast, a function declaration is hoisted and accessible from the whole scope. Its identifier uniquely refers to the single function object which is created once in the initialisation of the scope.