Hacker News new | ask | show | jobs
by Kiro 4862 days ago
The answer to "Why are there so many different ways to declare a function? What are the differences?" doesn't really answer the question.

No error:

  <script>

  myFunction();

  function myFunction() {};

  </script>
Error:

  <script>

  myFunction();

  var myFunction = function() {};

  </script>
A correct answer should explain why this happens in order to understand what the difference really is about.
2 comments

See this answer: http://news.ycombinator.com/item?id=5269731

In the second, the var myFunction gets hoisted to the top but not the function definition, which is why calling it produces an error. In the first, the whole function gets hoisted to the top.

I can take a stab at it.

All variables are hoisted to the top of a function, where they are defined as 'undefined'. This is confusing, I know - there is actually a difference between an undefined variable (accessing it will cause a ReferenceError) and a variable defined as 'undefined', which is in many cases identical to null, except in object syntax.

An example you can run in your inspector:

  function foo(){
    console.log(a);
    var a = "string";
  }
  function bar(){
    console.log(a);
  }
  foo(); // logs 'undefined'
  bar(); // throws ReferenceError
Why does this happen?

Well, this is because of the variable hoisting. Before running a function, the interpreter scans for any var definitions and 'hoists' them to the top of the function, where they are set to undefined. This leads to the strange situation where defining a variable after it's been accessed (as in foo()) actually prevents an exception.

The same is true of functions defined with the 'function name(){}' syntax. As opposed to the 'var name = function(){}' syntax, the entire function (including the definition of the function!) is hoisted to the top of the containing function. So this will work:

  function foo(){
    bar();
    function bar(){
      console.log("works!");
    }
  }
  foo();
This can be confusing but if used properly can be very helpful in refactoring your code. For instance, there are times when I've easily cleaned up code by just putting them into separate function definitions within the parent function:

  // old version
  function longFunction(){
    // 50 lines of code
    // awful, messy
  }

  function refactoredLongFunction(){
    doFirstThing();
    doSecondThing();
    doThirdThing();

    function doFirstThing(){
      // ...
    }
    // other function definitions
  }
This prevents a pattern I see in a lot of JS libraries that drives me nuts - defining functions at the top of a closure, then calling them at the bottom. I very much dislike scrolling 100 lines to see the actual action performed by a function. Using the above pattern leads to much more readable code, IMO.

If you'd like to know more about function and variable hoisting, this is a good read: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-...

> Before running a function, the interpreter scans for any var definitions and 'hoists' them to the top of the function, where they are set to undefined.

A little off topic, and completely trivial and petty, but it kinda bugs me when people talk about it as if the interpreter is moving variables around.

Moving variables around like that seems like a completely nutty thing to do, because it is. You can't give someone an explanation of the trade-offs as to why Javascript does it, because it doesn't. So hoisting is just presented as another thing Javascript does that makes it weird.

Really it's not actually moving anything, it's just an artefact of the same scoping rules used in lots of languages, compounded by allowing variables to be referenced before they're assigned.

Variables aren't moved, they behave as if they were moved.