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.
// 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.
// 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.
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.
// 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.
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.
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.
// 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.
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.
// 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
.
var person = {
age: 15,
print() {
console.log(this.age);
}
};
console.log(person.print()); // 15
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.
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.
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
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:
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🙂🙂..
Top comments (0)