BlogsDope image BlogsDope

Arrow Functions in JavaScript (ES6)

Nov. 17, 2020 JAVASCRIPT FUNCTION 5612

ECMAScript 2015 or ES 6 introduced arrow function expressions. It is a compact way of creating functions. Here is how you can create an arrow function.

(param1,param2,  paramN) => {
  //statements
s}

As opposed to regular functions, they do not require a function keyword, and they are anonymous. Let’s take an example to see the difference between a regular and an arrow function expression.

var numbers = [1,2,3,4,5]

//regular function
es5_square = numbers.map(function(number){
		return number*number
})
// arrow function
es6_square = numbers.map((number)=>{return number*number})

console.log(es5_square)
console.log(es6_square)

Output

(5) [1, 4, 9, 16, 25]
(5) [1, 4, 9, 16, 25]

The above code calculates the square of each element of the array numbers. As you can observe, the arrow function is more concise.

Let's make it shorter.

If the arrow function contains a single parameter, then we can omit the parenthesis. Consider the same example.

var numbers = [1,2,3,4,5]

// arrow function
es6_square = numbers.map(number=>{return number*number})

console.log(es6_square)

Output

(5) [1, 4, 9, 16, 25]

If the arrow function contains a single statement and that statement is a return statement, then you can omit the curly braces and the return keyword. Look at the following example.

var numbers = [1,2,3,4,5]

// arrow function
es6_square = numbers.map(number=>number*number)
console.log(es6_square)

Output

(5) [1, 4, 9, 16, 25]

However, if the arrow function contains zero or more than one parameter, then you have to include the parenthesis. Moreover, curly braces and return keyword are also necessary if the function has more than one statement.

var even = [2,4,6,8,10]
var odd = [1,3,5,7,9]


// sum of squares of corresponding even and odd numbers
es6_square = (a, b) => {
	num1 = a*a
	num2 = b*b
	return num1 + num2
}

for(i=0;i<5;i++)
{
console.log(es6_square(even[i], odd[i]))
}

Output

5
25
61
113
181

Handling of this


The behavior of this keyword is different in arrow and regular functions. In a regular function, this keyword belongs to the function’s parent or the object on which the function was invoked. However, in arrow functions, this value of the enclosing lexical scope is used. It refers to the current surrounding scope. Let’s take an example to understand this.

Consider the following example, where an object contains a property numbers array, and the method test displays it.

var obj = {
	numbers : [1,2,3,4,5],
	test : function(){
		console.log(this.numbers)
	}
}

obj.test()

Output

(5) [1, 2, 3, 4, 5]

Since it is a regular function, this refers to the object that called the method, i.e., obj.

Now, consider the following code.

var obj = {
	numbers : [1,2,3,4,5],
	test : function(){
		this.numbers.forEach(function(number){
			console.log(number + " belongs to the array " + this.numbers)
		})
	}
}

obj.test()

Output

1 belongs to the array undefined
2 belongs to the array undefined
3 belongs to the array undefined
4 belongs to the array undefined
5 belongs to the array undefined

Here, one would expect to get the same answer as in the previous example for this.numbers. As we know, this keyword belongs to the owner of the function. When this keyword is inside the object’s method, it belongs to that object. However, when it is a stand-alone or inside another method, it becomes out of scope, and it belongs to the Window Object. Since the Window object does not have a numbers property, it returns undefined.

Let’s discuss the two workarounds of this limitation in ES5. The first is to save the this value in a variable and use it where required. Look at the following code.

var obj = {
	numbers : [1,2,3,4,5],
	test : function(){
		var self = this;
		this.numbers.forEach(function(number){
			console.log(number + " belongs to the array [" + self.numbers +"]")
		})
	}
}

obj.test()

Output

1 belongs to the array [1,2,3,4,5]
2 belongs to the array [1,2,3,4,5]
3 belongs to the array [1,2,3,4,5]
4 belongs to the array [1,2,3,4,5]
5 belongs to the array [1,2,3,4,5]

The second workaround is to use bind to attach this (that refers to the method’s object) to the function inside the object’s method.

var obj = {
	numbers : [1,2,3,4,5],
	test : function(){
		this.numbers.forEach(function(number){
			console.log(number + " belongs to the array [" + this.numbers +"]")
		}.bind(this))
	}
}

obj.test()

Output

1 belongs to the array [1,2,3,4,5]
2 belongs to the array [1,2,3,4,5]
3 belongs to the array [1,2,3,4,5]
4 belongs to the array [1,2,3,4,5]
5 belongs to the array [1,2,3,4,5]

Since these are just the workarounds and not the actual solution, arrow functions provide a simple and straightforward solution. Let’s see how.

var obj = {
	numbers : [1,2,3,4,5],
	test : function(){
		this.numbers.forEach(number=>console.log(number + " belongs to the array [" + this.numbers +"]"))
	}
}

obj.test()

Output

1 belongs to the array [1,2,3,4,5]
2 belongs to the array [1,2,3,4,5]
3 belongs to the array [1,2,3,4,5]
4 belongs to the array [1,2,3,4,5]
5 belongs to the array [1,2,3,4,5]

The above code gives us the required output because this in arrow function uses lexical scoping. As arrow functions do not have their own this value, they use it from the enclosing scope.

Call() and Apply()


Since an arrow function does not have its own this, call() and apply() do not work in the desired way. Consider the following example.

var obj2 = {
	test : exponent => console.log(Math.pow(this.base, exponent) + " ")
}

var obj1 = {
	base: 4
}

obj2.test.call(obj1, 2)

Output

NaN

Where should we use (not use) arrow functions?


As arrow function provides the shorthand notation, they are preferred over regular functions for callbacks in methods like forEach(), map(), etc. Arrow function expressions make the code more readable and concise. As we have already seen above, no binding of this keyword gives us many advantages. However, before using arrow functions, we need to think about the required behavior of this keyword.

Arrow functions are not preferred to be used in the object’s methods. Let’s see an example

var obj = {
  number: 3,
  test: () => {
    this.number*this.number
  }
}

obj.test()
console.log(obj.number)

Output

3

3

As we can see, we did not get the desired answer because of the different behavior of this in arrow functions.

Arrow functions cannot be used as a constructor. Therefore, it will throw an error when we create objects using the new operator.

var Person = name => this.name = name;
var p1 = new Person("xyz")

Output

use of this in arrow function



Liked the post?
A computer science student having interest in web development. Well versed in Object Oriented Concepts, and its implementation in various projects. Strong grasp of various data structures and algorithms. Excellent problem solving skills.
Editor's Picks
0 COMMENT

Please login to view or add comment(s).