Arrow Functions in JavaScript, How is it different? 
Tags: javascript, beginners, codenewbie, webdev
Published: 2020-10-18 19:25:57

JavaScript has seen a lot of changes in the past few years making it robust, elegant & the primary choice language of the web. Ever since ES6 was released, JavaScript has become a different ballgame altogether with various drastic changes adding to it's elegance. With each successive ES release, it brought a lot of cool stuff to the table. One such major breakthrough came with the release of ES6 which introduced features like the `let` & `const` keywords, `template literals`, the `class` keyword, `modules`, `destructuring` and a lot more. Among these hallmark was the **'Arrow Functions'**. 

Ever since it's inception, it has been widely acclaimed & adopted by the JS developers/community. It is been widely used in libraries & big frameworks like Angular, React, Vue, etc. It has completely changed the way we look & write functions in JS making it short and concise. Before diving in, let's talk briefly about traditional ways of writing functions in JavaScript.

####Functions in JS:
There are a few different ways to define a function in JavaScript.
* Function declaration:

A function declaration defines a named function. To create a function declaration you use the `function` keyword followed by the name of the function.
```javascript
// function declaration
function add(a, b){
   return a + b;
}

console.log(add(1,2)); //3
```

* Function expression:

A function expression is very similar to and has almost the same syntax as a function declaration. The main difference between a function expression and a function declaration is the function name, which can be omitted in function expressions to create anonymous functions. In simple words, a function expression can be defined as an anonymous function assigned to a variable.
```javascript
// function expression
var add = function (a, b){
   return a + b;
}

console.log(add(1,2)); //3
```

* Function() Constructor:

The `function` statement is not the only way to define a new function, you can define your function dynamically using **Function()** constructor along with the **new** operator. This is how we can use the Function() constructor to create functions.
```javascript
var add = new Function('a','b','return a+b;');

console.log(add(1,2)); //3
```
However creating functions using this method is not recommended. Calling the constructor directly can create functions dynamically but suffers from security and similar performance issues.

Apart from the above mentioned methods, there is a new way to define functions in JavaScript post the release of ES6 and that is the **Arrow Function**.
 
####Arrow Functions:
The Arrow function is the latest way to define a function in JS. It is a shorter syntax for writing function expressions. An arrow function is a cleaner, concise & a compact alternative to a traditional function expression, but is limited and can't be used in all situations. Here is how we write the above function using the Arrow function syntax.
```javascript
// arrow function
var add = (a,b) => {
   return a + b;
}
```
In an arrow function , we don't require a `function` keyword. Instead we use a fat arrow **(=>)** between the parameters and the body of the function. The above arrow function can also be compacted further. If the body of our function includes only a single line, we can write the function like this.
```javascript
var add = (a,b) => { return a + b; } 
```
Also, if there is a single line of code in the function body & returns a value, we can eliminate both the `return` keyword and the `{}` braces completely like this.
```javascript
var add = (a,b) => a + b;  
```
Here are the 2 methods: The latter arrow function that we have is exactly equivalent to the former function expression shown above.
```javascript
// function expression
var add = function (a, b){
   return a + b;
}

// arrow function
var add = (a,b) => a + b;  
```
You can see, this syntax is cleaner & more compact and makes you write less lines of code.😃 

####Note:
If the arrow function has a single parameter, we can skip writing the parenthesis `()` i.e. we need not require the parenthesis `()` for enclosing the single parameter. But if the function has more than one parameter, parenthesis is required.
```javascript
var greet = name => console.log('Hi' + name);

greet('Tahir'); // 'Hi Tahir'
```

####How are Arrow functions different?
The obvious question you must be asking yourself is what was the need for introducing arrow functions and why should I use it. One good reason would be, that it would make your code look more readable & smaller by eliminating good amount of lines. 
Further more, I will replace all my existing functions that I have defined using function declaration/expression with Arrow functions and my code will work the same as before. Big deal? The answer to that is **NO!!**. Don't do that.  

Even though at first it might look like there is just a syntax difference between them, but that is not true. There are quite subtle differences between the Arrow functions & the traditional methods. Let's discuss what are they. 

* **'args'** object:

Arrow functions don't have access to `arguments` object. Let's understand this with an example.
```javascript
// function expression
var add= function(a,b) {
   console.log(arguments[0]); // 1
   console.log(arguments[1]); // 2
   return a + b;
}

add(1,2); // 3

// arrow function
var add = (a,b) => console.log(arguments[0]);

add(1,2); // arguments is not defined
```
* Arrow functions don't have their own **'this'**:

The behavior of this inside of an arrow function differs considerably from the regular function’s this behavior. It does not have its own bindings to `this` and should not be used as `methods`.
```javascript
var person = {
  age: 15,
  print() {
    console.log(this.age);
  }
};

console.log(person.print()); // 15
```
```javascript
var person = {
  age: 15,
  print: () => {
    console.log(this.age);
  }
};

console.log(person.print()); // undefined
```
**Traditional functions** default `this` to the window scope. **Arrow functions** do not default `this` to the window scope, rather they execute in the scope they are created.
```javascript
var person = {
   eat() {
      setTimeout(function(){
         console.log('this', this);
      }, 1000);
   }
};

person.eat(); // {Window Object}
```
Upon invoking **person.eat()**, this prints a `window` object. The reason this happened because here, the callback function inside **setTimeout()** is not part of any object. It's a standalone function. When we call a function as a standalone function outside of an object, by default `this` points to window object.

```javascript
var person = {
   eat() {
      setTimeout(() => {
         console.log('this', this);
      }, 1000);
   }
};

person.eat(); // {person Object}
```
This can be resolved using an Arrow function because they don't rebind `this`. In other words, if we change the callback to an arrow function, it will inherit the `this` keyword. In the callback function, because we have used the **arrow function syntax**, the value of `this` is not reset. Instead it inherits the value of `this` in the context in which this code is defined.

* Arrow functions cannot be used as a **constructor**:

If you are aware of constructor functions in JavaScript, then you should know that a regular function can easily construct objects. For example, the `Person()` function creates instance of a person class
```javascript
function Person(name) {
  this.name = name;
}

var person1 = new Person('Tahir');
person1 instanceof Person; // true
```

The arrow function resolves `this` lexically. In another words, the arrow function doesn’t define its own **execution context**. A consequence of `this` resolved lexically is that an arrow function **cannot** be used as a constructor. If you try to invoke an arrow function prefixed with `new` keyword, JavaScript throws an error:
```javascript
var Person = (name) => {
  this.name = name;
}

var person1 = new Person('Tahir'); // TypeError: Person is not a constructor
```

That's all there is to **Arrow Functions**. In a nutshell, we simply cannot interchangeably use `Arrow functions` over `Function expressions` or vice versa. The right way to go would fully depend upon the requirement of how you want to build things as per need. Hope this was helpful. Happy Learning🙂🙂..