Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is neither a scope problem nor is it a closure problem. The problem is in understanding between <strong>declarations</strong> and <strong>expressions</strong>.</p> <p>JavaScript code, since even Netscape's first version of JavaScript and Microsoft's first copy of it, is processed in two phases:</p> <p>Phase 1: compilation - in this phase the code is compiled into a syntax tree (and bytecode or binary depending on the engine).</p> <p>Phase 2: execution - the parsed code is then interpreted.</p> <p>The syntax for function <strong>declaration</strong> is:</p> <pre><code>function name (arguments) {code} </code></pre> <p>Arguments are of course optional (code is optional as well but what's the point of that?).</p> <p>But JavaScript also allows you to create functions using <strong>expressions</strong>. The syntax for function expressions are similar to function declarations except that they are written in expression context. And expressions are:</p> <ol> <li>Anything to the right of an <code>=</code> sign (or <code>:</code> on object literals).</li> <li>Anything in parentheses <code>()</code>.</li> <li>Parameters to functions (this is actually already covered by 2).</li> </ol> <p><strong>Expressions</strong> unlike <strong>declarations</strong> are processed in the execution phase rather than the compilation phase. And because of this the order of expressions matter.</p> <p>So, to clarify:</p> <hr> <pre><code>// 1 (function() { setTimeout(someFunction, 10); var someFunction = function() { alert('here1'); }; })(); </code></pre> <p>Phase 1: compilation. The compiler sees that the variable <code>someFunction</code> is defined so it creates it. By default all variables created have the value of undefined. Note that the compiler cannot assign values yet at this point because the values may need the interpreter to execute some code to return a value to assign. And at this stage we are not yet executing code.</p> <p>Phase 2: execution. The interpreter sees you want to pass the variable <code>someFunction</code> to setTimeout. And so it does. Unfortunately the current value of <code>someFunction</code> is undefined.</p> <hr> <pre><code>// 2 (function() { setTimeout(someFunction, 10); function someFunction() { alert('here2'); } })(); </code></pre> <p>Phase 1: compilation. The compiler sees you are declaring a function with the name someFunction and so it creates it.</p> <p>Phase 2: The interpreter sees you want to pass <code>someFunction</code> to the setTimeout. And so it does. The current value of <code>someFunction</code> is its compiled function declaration.</p> <hr> <pre><code>// 3 (function() { setTimeout(function() { someFunction(); }, 10); var someFunction = function() { alert('here3'); }; })(); </code></pre> <p>Phase 1: compilation. The compiler sees you have declared a variable <code>someFunction</code> and creates it. As before, its value is undefined.</p> <p>Phase 2: execution. The interpreter passes an anonymous function to setTimeout to be executed later. In this function it sees you're using the variable <code>someFunction</code> so it creates a closure to the variable. At this point the value of <code>someFunction</code> is still undefined. Then it sees you assigning a function to <code>someFunction</code>. At this point the value of <code>someFunction</code> is no longer undefined. 1/100th of a second later the setTimeout triggers and the someFunction is called. Since its value is no longer undefined it works.</p> <hr> <p>Case 4 is really another version of case 2 with a bit of case 3 thrown in. At the point <code>someFunction</code> is passed to setTimeout it already exists due to it being declared.</p> <hr> <p><em>Additional clarification:</em></p> <p>You may wonder why <code>setTimeout(someFunction, 10)</code> doesn't create a closure between the local copy of someFunction and the one passed to setTimeout. The answer to that is that function arguments in JavaScript are always, <em>always</em> passed by value if they are numbers or strings or by reference for everything else. So setTimeout does not actually get the variable someFunction passed to it (which would have meant a closure being created) but rather only gets the object that someFunction refers to (which in this case is a function). This is the most widely used mechanism in JavaScript for breaking closures (for example in loops).</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload