1

I'm just wondering how to write ES6 functions properly. I know that it depends on personal preference but what are the pros and cons?

function foo() {
  ...
}

vs.

const foo = () => {
  ...
};

vs.

const foo = function () {
  ...
};

vs.

const foo = function bar() {
  ...
};

The airbnb style guide recommends the latter. But it makes no sense to me to define two names for one function.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Pawel
  • 1,560
  • 1
  • 10
  • 11
  • 1
    I prefer the very first :D – Suresh Atta Jul 04 '17 at 07:33
  • I think could be related to assigning a name to each anonymous function to ensure always you can trace your errors properly – dloeda Jul 04 '17 at 07:34
  • Using a *named function expression*, the last one, allows for debugging ease as it actually tells you the function name instead of an anonymous function. – Andrew Li Jul 04 '17 at 07:34
  • 3
    These notations are not equivalent : "this" is not treated the same using arrow notation. – Alice Oualouest Jul 04 '17 at 07:36
  • 1
    You have to learn the difference between an arrow function, a function declaration and a function expression. See [Arrow function vs function declaration / expressions: Are they equivalent / exchangeable?](https://stackoverflow.com/q/34361379/218196) and [var functionName = function() {} vs function functionName() {}](https://stackoverflow.com/q/336859/218196) . Finally you can find more information about *named* function expression at [Why using named function expressions?](https://stackoverflow.com/q/15336347/218196). Then choose whatever fulfills your needs. – Felix Kling Jul 04 '17 at 07:37
  • I suppose depends on the environment too, I don't like same recommendations in node.js back-end and front-end – dloeda Jul 04 '17 at 07:38
  • @FelixKling thank you for the good stuff. Makes many things clearer. – Pawel Jul 04 '17 at 08:26

2 Answers2

3

Using a function declarations means that you'll deal with function declaration hoisting in which all functions are processed before any code execution so you can technically use them before they are defined, as they are hoisted up to the top, and you won't have block scoping, as they would be function scoped:

foo(); //can be used before declaration appears!

function foo() {
  { //new block
    function bar() { 
      alert(1);
    }
  }
  bar(); //no problem, is function scoped
}
foo(); //alerts 1!

With function expressions, there will be no hoisting and you'll have block scoping if you use let or const:

function foo() {
  { //new block
    const bar = () => { 
      alert(1);
    }
  }
  bar(); //ReferenceError: Can't find variable: bar
}
foo();

Finally, using a named function expression allows for the error to provide a named for the function, instead of just an anonymous function for better debugging. Thus: prefer the last choice. It has expected block scoping, (it still has hoisting but it's invalid to access it before declaration in code), and it allows for a better debugging experience.

Also, don't forget that arrow functions do not bind their own this but take the this of the enclosing context! Function declarations always have a this referring to the global object window or undefined in strict mode.

Andrew Li
  • 55,805
  • 14
  • 125
  • 143
  • 1
    Best answer for me. Thank you! – Pawel Jul 04 '17 at 08:24
  • Note that functions are automatically named when you make a variable (e.g. `const f = function() {}`; `f.name === 'f'`): ["If *hasNameProperty* is false, perform SetFunctionName(*rval*, GetReferencedName(*lref*))."](https://tc39.github.io/ecma262/#sec-assignment-operators-runtime-semantics-evaluation) – Nebula Jul 04 '17 at 11:48
0

The first one has an advantage of avoiding errors related do hoisting, so you can use the function before its declaration.

With the other options, you can use them only after the declaration, because before that point, they are variables with undefined value (due to hoisting). So I would say the first option is the safest one.

Alberto Trindade Tavares
  • 10,056
  • 5
  • 38
  • 46
  • I respectfully disagree. I would say only using after declaration is a good thing, plus function declarations are function scoped, but expressions with let or const are block scoped. Finally, `this` treated a lot differently. – Andrew Li Jul 04 '17 at 07:56