title: JavaScript: Understanding closures and hoisting
body: <p>I understand that function declarations are hoisted to the top of their scope. This allows us to use those functions before they're actually declared in JavaScript:</p>
  
  <pre><code>sayHello(); // It works!
  
  function sayHello() {
    console.log('Hello');
  }
  </code></pre>
  
  <p>I also understand that closures enable functions to retain references to variables declared within the same scope:</p>
  
  <pre><code>function outerFxn() {
    let num = 0;
  
    function innerFxn() {
      console.log(num);
      num++;
    }
  
    return innerFxn;
  }
  
  const logNum = outerFxn();
  logNum(); // 0
  logNum(); // 1
  logNum(); // 2
  </code></pre>
  
  <p>So far so good. But here's some weirdness that I'm hoping someone can explain exactly what's going on...</p>
  
  <h2>Scenario 1: understandable closure</h2>
  
  <pre><code>function zero(cb) {
    return setTimeout(cb, 0);
  }
  
  function test1() {
    let txt = 'this is a test message';
  
    function log() {
      console.log(txt);
    }
  
    zero(log);
  }
  </code></pre>
  
  <p>In the example above, the <code>log</code> function retains a reference to the scope in which it was created, holding on the the <code>txt</code> variable. Then, when executed later on in the <code>setTimeout</code>, it successfully log's the <code>txt</code> variable's value. Great. Then there's this...</p>
  
  <h2>Scenario 2: what is happening?</h2>
  
  <pre><code>function zero(cb) {
    return setTimeout(cb, 0);
  }
  
  function test1() {
    function log() {
      console.log(txt);
    }
  
    let txt = 'this is a test message';
  
    zero(log);
  }
  </code></pre>
  
  <p>I've moved the <code>log</code> function declaration to the top of the scope (it would have been hoisted there anyway, right?), <em>then</em> I'm declaring the <code>txt</code> variable below it. This all still works and I'm not sure why. How is <code>log</code> retaining a reference to the <code>txt</code> variable when <code>let</code>'s and <code>const</code>'s aren't hoisted up? Are closure scopes analyzed <em>as-a-whole</em>? I could use a bit of clarity on what the JavaScript engine is doing step by step here. Thank you SO land!</p>