The main difference between arrow functions and regular functions is execution context (i.e. the value of this). Technically speaking, most other differences often mentioned either stem from this one or are side effects of it.
In a regular function, this is dynamic and depends on how the function was invoked:
function simple() { return this; }const object = { method() { return this; }};class Class { classMethod() { console.log(this); }}const instance = new Class();simple(); // `this` refers to the global objectnew simple(); // `this` refers to the newly created instanceobject.method(); // `this` refers to `object`simple.call(object); // `this` refers to `object`instance.classMethod(); // `this` refers to `instance`setTimeout( instance.classMethod, 0 // `this` refers to the global object);
Arrow functions, unlike regular ones, don’t define their own execution context. Therefore this inside an arrow function always refers to the lexical this (i.e. the scope in which the arrow function was defined).
const simple = () => this;const object = { method: () => this};class Class { classMethod = () => { console.log(this); }}const instance = new Class();simple(); // `this` refers to the global objectnew simple(); // Uncaught TypeError: simple is not a constructorobject.method(); // `this` refers to the global objectsimple.call(object); // `this` refers to the global objectinstance.classMethod(); // `this` refers to `instance`setTimeout( instance.classMethod, 0 // `this` refers to `instance`);
Arrow functions cannot be used as constructors and will throw a TypeError when used with the new keyword.
// Bad - `this` doesn't refer to the elementbutton.addEventListener('click', () => { this.classList.toggle('active'); // Error});// Good - use regular functionbutton.addEventListener('click', function() { this.classList.toggle('active'); // Works});
// Error - arrow functions can't be constructorsconst Person = (name) => { this.name = name;};new Person('Alice'); // TypeError// Good - use regular function or classfunction Person(name) { this.name = name;}new Person('Alice'); // Works