10

For example, in this Redux video, the instructor always uses syntax like

const counter = (state=0, action) => {
   ... function body here
}

where I would just use the "traditional"

function counter(state=0, action) {
   ... function body here
}

Which is actually shorter and, IMO, clearer. It's easier to scan the fairly even and structured left edge of the page for the word "function" than scan the raggedy right edge for a small "=>".

Other than this, and trying to be objective, not opinion, is there some useful difference or advantage to the newfangled syntax?

  • 3
    This question on StackOverflow may interest you: stackoverflow.com/questions/34361379/… – Vincent Savard Jan 16 '18 at 18:53
  • 3
    I'm no JavaScript expert, but I'm guessing const helps ensure the function doesn't get redefined later on. – MetaFight Jan 16 '18 at 19:13
  • Thanks @VincentSavard, that's perfect, and basically what I expected: Other than "this", and prototype/class stuff, there appears to be no real difference. – user949300 Jan 16 '18 at 19:44
  • 3
    @user949300 There is a difference, the one MetaFight mentions. Also, protype / "this stuff" quickly become critical distinctions, as well. – msanford Jan 16 '18 at 20:00
  • 1
    Long story short: You should value clear and concise over an edge-case benefit. – Wayne Bloss Jul 10 at 15:04
9

Function statements (named functions, 2nd syntax shown) are hoisted to the top of the full lexical scope, even those behind arbitrary and control blocks, like if statements. Using const (like let) to declare a variable gives it block scope, stops the full hoisting (hoisting to mere block), and ensures it cannot be re-declared.

When concatenating scripts together, or some using other package-building tools, function hoisting can break conflicting scripts in ways that are difficult to debug as it fails silently. A re-declared const will throw an exception before the program can run, so it's much easier to debug.

  • Thanks. good answer. I've mainly worked on smaller JS projects, or node.js server projects where they have a good module system for namespacing. But just starting on a more client-side project using bundlers and this is good insight. – user949300 Jan 17 '18 at 17:55
  • 2
    Just a note that eslint no-func-assign may catch this redeclaration issue. – user949300 Jan 26 '18 at 1:18
  • 2
    Writing code that has confusing signals in order to get the benefits of a statically typed language is a reason to use Typescript, not const. It's a bit short-sighted, IMO, to start using const everywhere for this reason in the age of eslint, webpack, babel and so forth. Nobody is concatenating files together manually anymore for at least a decade now. – Wayne Bloss Jul 10 at 14:54
2

Here's why you should use function:

  1. The signaling is clear and concise. This is far more beneficial than any of the edge-case hoisting concerns that are listed in the other answer.

  2. You actually want hoisting within modules because as you can see from the code below, the const declaration of tryDoTheThing fail silently and won't be caught until you try to call it.

  3. Most juniors that I come into contact with start using const to declare every function because it's a fad right now, like using spaces over tabs or making everything functional!!! because "OOP bad". Don't do that. You don't want to be that guy who follows fads without fully understanding the implications.

via https://gist.github.com/stephenjfox/fec4c72c7f6ae254f31407295dc72074


/*
This shows that, because of block-scoping, const function references must be
invoked in-order or else things will fail silently.
const's are added the name space serially (in the order in which they appear)
and much of the body isn't declared when we first try to invoke or functions
*/


const tryDoTheThing = () => {
  console.log(`This is me trying to be awesome ${getAwesome()}`)
}


// "getAwesome is not defined", because it is referenced too early
tryDoTheThing() // comment to see the rest work


const getAwesome = () => (+((Math.random() * 10000).toString().split('.')[0]))


const doTheThing = () => {
  console.log(`This is awesome! ${getAwesome()}`)
}

doTheThing() // prints

vs

/*
Function declarations are given two passes, where the first lifts them to
the top of the namespace, allowing "out of order" usage
*/

doTheThing();


function doTheThing() {
  console.log(`This is awesome number ${getAwesome()}`)
}

function getAwesome() {
  return (+((Math.random() * 10000).toString().split('.')[0]))
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.