2

In John Resig's 'Learning Advanced Javascript' slide #6 (http://ejohn.org/apps/learn/#6) shows that you can use a function before it's defined. Here is the code:

var canFly = function(){ return true; }; 
window.isDeadly = function(){ return true; }; 
assert( isNimble() && canFly() && isDeadly(), "Still works, even though isNimble is moved." ); 
function isNimble(){ return true; }

However, I noticed the following code does not pass the test.

assert( canFly(), "Still works, even though isNimble is moved." ); 
var canFly = function(){ return true; }; 

It looks like assigning an anonymous function to a variable is different from defining a named function. Why is that? And what is the name of this concept that describe the ability to use function before its definition in a language?

Ivan Vashchenko
  • 1,214
  • 2
  • 11
  • 19
  • possible duplicate of [JavaScript 'hoisting'](http://stackoverflow.com/questions/15311158/javascript-hoisting) – Alexei Levenkov Dec 13 '13 at 01:13
  • The search term is "JavaScript hoisting" - check out linked duplicate (with slightly different code, but good links) - variables are visible for whole function (way before `var`), but will only get value during first assignment. – Alexei Levenkov Dec 13 '13 at 01:15
  • @AlexeiLevenkov Isn't the top answer there more about the scope rather than the order of things? – Dennis Jaheruddin Dec 13 '13 at 01:27
  • @DennisJaheruddin - somewhat - but you can read it as an explanation of how function declared at the end of scope is immediately visible at the beginning of scope. – Alexei Levenkov Dec 13 '13 at 01:39

3 Answers3

4

The function declaration:

function isNimble(){ return true; }

is defined when the code is parsed (i.e. before any code is executed), wherease the function expression:

var canFly = function(){ return true; };

is evaluated when the code is running, so the function isn't callable until after this line is executed. That's the difference causing the second example to fail.

RobG
  • 142,382
  • 31
  • 172
  • 209
mechanicalfish
  • 12,696
  • 3
  • 46
  • 41
2

When Javascript creates the execution context it first creates all variables, functions and arguments. Next it assigns them values. Since isNimble is a globally defined function it is created in the first stage along with canFly however canFly is not assigned the function until after the second stage when assignment occurs. The assignment does not occur before the execution of the assert statement.

See: http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/

Here is an excerpt from the above link that explains it well:

Execution Context in Detail

So we now know that every time a function is called, a new execution context is created. However, inside the JavaScript interpreter, every call to an execution context has 2 stages:

Creation Stage [when the function is called, but before it executes any code inside]:
    Create variables, functions and arguments.
    Create the Scope Chain.
    Determine the value of "this".
Activation / Code Execution Stage:
    Assign values, references to functions and interpret / execute code.
Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
  • "Since `isNimble` is a globally defined function" should be "Since `isNimble` is defined using a *function declaration*". – RobG Dec 13 '13 at 03:11
  • In the quoted text, note that [when entering function code](http://ecma-international.org/ecma-262/5.1/#sec-10.4.3) the *ThisBinding* is set first, not last. – RobG Dec 13 '13 at 03:15
0

Here is the answer to why it happens (and has to happen). This does not depend much on the language and I just hope that I didn't use strange terminology for javascript.

When you are at a certain point in the code, you should know what happens when you call a function. Therefore the function is typically defined only once, or an order of precedence is known. Functions are not really designed to change, so it makes sense to have them available to the user even if they are defined in the bottom of the code.

When you call a variable, you want to have the value of that variable at the time when you call it. If you didn't define the variable before you call it, it should not work. Amongst others, this allows you to assign different functions to the same variable at different point in the code.


So to conclude: do not confuse 'after' with 'below' and just consider simple function definitions to occur before variable assignments (even if you assign a function to that variable).

Dennis Jaheruddin
  • 21,208
  • 8
  • 66
  • 122
  • 1
    It actually depends on language - and JavaScript moves all declaration to top of the scope (hoisting). Some languages would give an error if using variable/function before declaration... – Alexei Levenkov Dec 13 '13 at 01:32