What Is an Arrow Function in JavaScript? How Is It Different From a Regular Function?

October 27, 2022

☕️ Support Us
Your support will help us to continue to provide quality content.👉 Buy Me a Coffee

Arrow function is a function expression introduced in ES6. Some features of an arrow function are different from a regular function expression. It is a common question in JavaScript interviews, so make sure you know the difference.

The difference between arrow function and regular function

There are four main differences between arrow functions and regular functions, which we will explain in detail below:

  1. The syntax of the arrow function is different. It is more concise
  2. The arrow function does not have its own binding to this, and we cannot directly change this in an arrow function
  3. Arrow functions do not have their own arguments
  4. Arrow functions cannot be used as constructors. Calling them with new throws a TypeError

The syntax is more concise

Compared with regular functions, the syntax of arrow functions is more concise. In addition to eliminating the function keyword, if there is only one parameter, we can omit the parentheses; if there is only one line of code, it simply returns a variable or a simple expression directly, and the curly braces and return can be omitted. Examples are as follows:

// regular function
let addOne = function (n) {
  return n + 1;
};
// ES6 arrow function, when there is only one parameter, the parentheses of the parameter can be omitted
let addOne = (n) => {
  return n + 1;
};
// ES6 arrow function, when there is only one line, omit curly braces and return
let addOne = (n) => n + 1;

this value is different from a regular function

An arrow function does not have its own this binding. The this value of an arrow function is determined at the beginning of its definition. In an arrow function, this is lexically scoped, meaning it is inherited from the parent scope. Also, we cannot use call, applyand bind to bind this value in arrow functions, the bound value will be invalid. The this value of a regular function is determined based on how the function is called. For details, please refer to "What is the value of this in JavaScript".

this can be bound in regular functions (code example)

const obj = {
  num: 100,
};

window.num = 2020;

const add = function (a, b, c) {
  return this.num + a + b + c;
};

// Bind this value to obj, obj's num is 100, so resultCall is 106
const resultCall = add.call(obj, 1, 2, 3);
console.log(resultCall); // 106

The this binding in the arrow function will be invalid, the following is an example of the code binding

const obj = {
  num: 100,
};

window.num = 2020;

const add = (a, b, c) => this.num + a + b + c;

// Binding this is invalid, the this of the add function will be window
// So num will be 2020 and resultCall will be 2026
console.log(add.call(obj, 1, 2, 3)); // 2026

Taking advantage of the fact that arrow functions do not have their own this value, it is very suitable for use in setTimeout() and EventTarget.prototype.addEventListener() and other methods, because it will be automatically bound in its lexical scope. You can see that in setTimeout below, there is a difference between this using regular functions and arrow functions:

// regular function version, this value is NaN in this case
const obj = {
  count: 10,
  doSomethingLater() {
    setTimeout(function () {
      // It is a regular function, so this points to window
      this.count++;
      console.log(this.count); // NaN (because there is no count in windoww)
    }, 300);
  },
};
obj.doSomethingLater();

// arrow function version
const obj = {
  count: 10,
  doSomethingLater() {
    // It is an arrow function, so this will be based on the this value of the closest parent, here is obj
    setTimeout(() => {
      this.count++;
      console.log(this.count); // 11 (obj's count is originally 10, 10++ will be 11)
    }, 300);
  },
};
obj.doSomethingLater();

Do not have its own arguments

Unlike regular functions, arrow functions do not have an arguments object, but the advantage is that arrow functions can get the arguments object of the nearest non-arrow function, as shown in the following example

arguments code example in arrow function

// Arrow functions don't have their own arguments, so they look for their parent
// The parent layer here is the global environment, so find the arguments variable in the global environment
// arguments[0] is 1 in the global environment
const arguments = [1, 2, 3];
const arr = () => arguments[0];
arr(); // 1

// A regular function has an arguments object, which is the parameter passed in. The arguments here are [3]
// so arguments[0] will also be 3
// f() would be 3 + 3
function foo(n) {
  const f = () => arguments[0] + n;
  return f();
}
foo(3); // 3 + 3 = 6

If you need to use all the parameters of the arrow function, you can use the following rest operator to get them

let nums = (...nums) => {
  console.log(nums);
};
nums(1, 2, 3, 4, 5); //[1,2,3,4,5]

Cannot be used as a constructor

Arrow functions cannot be used as constructors, in other words, they cannot be called with the new keyword or an error will be reported

const arrowFun = () => {};
new arrowFun(); // error: arrowFun is not a constructor

Summarize

  1. The syntax of the arrow function is different. It is more concise
  2. The arrow function does not have its own binding to this, and we cannot directly change this in an arrow function
  3. Arrow functions do not have their own arguments
  4. Arrow functions cannot be used as constructors. Calling them with new throws a TypeError
☕️ Support Us
Your support will help us to continue to provide quality content.👉 Buy Me a Coffee