DEV Community

loading...

Discussion on: Arrow Functions

Collapse
peerreynders profile image
peerreynders • Edited

One disadvantage I feel is, we can not use arrow function to define constructor.

There are other disadvantages:

  • class methods are shared via the prototype object so there is only one function value per method per class.
  • arrow functions are function values bound to an instance field - so there is a function value dedicated to each object created by the class. This has implications if you plan to use inheritance.
class A {
  myArrow = () => {
    console.log('A.myArrow()');
  }

  myMethod() {
    console.log('A.myMethod()');
  }
}

class B extends A {
  myArrow = () => {
    super.myArrow(); // arrow function exists on 
                     // public class field of A but
                     // but is not available on 
                     // the prototype chain via `super`
    console.log('B.myArrow()');
  }

  myMix() {
    super.myArrow(); // same problem
    console.log('B.myMix()');
  }

  myMethod() {
    super.myMethod(); // just works
    console.log('B.myMethod()');
  }
} 

let myB = new B();

myB.myMethod(); // 'A.myMethod()'
                // 'B.myMethod()'
myB.myMix();    // Uncaught TypeError: (intermediate value).myArrow is not a function at B.myMix
myB.myArrow();  // Uncaught TypeError: (intermediate value).myArrow is not a function at B.myArrow
Enter fullscreen mode Exit fullscreen mode

So only use arrow functions in classes when there is a very good reason to (i.e. to avoid having to use bind anyway).

Classes often use arrow functions as reusable event listeners. However EventTarget.addEventListener() can also accept objects as listeners as long as they implement EventListener.handleEvent().

React's synthetic event system doesn't support object event listeners however object event listeners can be used via useEffect().


Technically arrow functions cannot be named.

const randomize = () => Math.random();
Enter fullscreen mode Exit fullscreen mode

All that is happening here is that an anonymous function expression is bound to a variable name. To get a named function expression:

const randomize = function randomize() {
  return Math.random();
};
Enter fullscreen mode Exit fullscreen mode

What is the difference?
In the following the locally available function name fibRec is used:

const fn = function fibRec(n2, n1, i) {
  const next = n2 + n1;
  return i > 1 ? fibRec(n1, next, i - 1) : next;
}

const fib = function(n) {
  return n > 1 ? fn(0, 1, n - 1) : n > 0 ? 1 : 0;
}

console.log(fib(20)); // 6765
Enter fullscreen mode Exit fullscreen mode

With arrow functions the variable name fn from the creating scope has to be used:

const fn = (n2, n1, i) => i > 1 ? fn(n1, n2 + n1, i - 1) : n2 + n1;

const fib = (n) => n > 1 ? fn(0, 1, n - 1) : n > 0 ? 1 : 0;

console.log(fib(20)); // 6765
Enter fullscreen mode Exit fullscreen mode

Contrast this with a function declaration which cannot be unnamed.

function randomize() {
  return Math.random();
};
Enter fullscreen mode Exit fullscreen mode

The advantage of a function declaration is that it is hoisted to the top of the scope. This works:

const SOME_CONSTANT = 2 * Math.PI;

console.log(calculate(10)); // 62.83185307179586

function calculate(radius) {
  return SOME_CONSTANT * radius;
}
Enter fullscreen mode Exit fullscreen mode

This does not work:

const SOME_CONSTANT = 2 * Math.PI;

console.log(calculate(10)); // Uncaught ReferenceError: Cannot access 'calculate' before initialization

const calculate = (radius) => SOME_CONSTANT * radius;
Enter fullscreen mode Exit fullscreen mode

This doesn't work either:

const SOME_CONSTANT = 2 * Math.PI;

console.log(calculate(10)); // TypeError: calculate is not a function

var calculate = (radius) => SOME_CONSTANT * radius;
Enter fullscreen mode Exit fullscreen mode

While var calculate is hoisted, the assignment isn't.