What is arrow function?
An arrow function, also known as fat arrow function is more concise syntax for writing a function expression, but it does not bind own this, arguments, super or new.target
Those functions cannot be used as function constructors, and non-method functions (lack of this bindings)
The biggest advantage of using arrow function is to accomplish the same result with fewer lines of code and much less typing.
//basic usage with single argument
const test = (param1) => { /* do something here */ }
//when there is just one param you can skip parentheses
const test2 = param2 => { /* do something here */ }
//when do function body just return expression you might
//go even further and skip curly braces
const test3 = item => item.id;
//which is equivalent to:
function test3(item){
return item.id;
}
However in some cases you must use parenthesis
//arrow function without arguments
const test4 = () = { /* do something here */ };
//arrow function with more than one arguments
const test4 = (param1, param2) => { /* do something here */ } ;
//rest operator
const test5 = (...options) => { /* do something here */ } ;
//default params
const test5 = (param1 = [], param2 = true) => { /* do something here */ } ;
If you want to implicitly return an object and still want to omit curly braces you have to wrap your object with parenthesis
const getTestItem = () => ({ name: 'test' }); // will return { name: 'test' }
If you ever come across something like this:
const logger = store => next => action => {
console.log(action);
next(action);
}
Don't be overwhelmed, as this pattern is called currying and it simply translates to:
function logger(store){
return function(next){
return function(action){
console.log(action);
next(action);
}
}
}
Typical use cases
Arrays operations
Whenever you encounter that your code is getting too verbose and function you are creating is not a method nor constructor, you may find this handy:
const users = [
{id: 1, name: 'John', age: 26},
{id: 2, name: 'Thomas', age: 15},
{id: 3, name: 'Kate', age: 23 }
];
const grownUps = users.filter(user => user.age > 18);
//instead of more verbose:
const grownUps2 = users.filter(function(user){
return user.age > 18;
});
Shorter asynchronous syntax
somePromise().then(function(response){ rerturn response.json(); })
.then(function(response){ /* process response */ })
.catch(function(error){ /* process errror */ });
//can become
somePromise().then(response => response.json())
.then(response => { /* process response */ })
.catch(error => { /* process error */ });
Using with this
Not binding this could be an advantage in certain situations, as functions declared with function keyword always declare new this.
//part of an object
//...
saveItem: function() {
//we have to store this in a vm variable
// to have a reference to a parent object
let vm = this;
this. $http.post('item', this.item).then(function (response) {
//'this' here points to function(response){} instead of parent object
//that's why we use vm instead
vm.item = response.item;
},function(error) {
console.log(error);
});
}
//with arrow function we don't need to store this in vm var
//(as arrow function doesn't have own this)
//...
saveItem: function() {
this. $http.post('item', this.item).then(response => {
//'this' here points to parent object
//that's why we don't need to use vm here
this.item = response.item;
}, error => {
console.log(error);
});
}
Constructors
You cannot use arrow functions for object constructors. You should use either new ES2015 class syntax or ES5 function keyword for that.
const Person = (name) => {
this.name = name;
}
const tom = new Person(); //throws TypeError: Person is not constructor
//ES2015
class Person{
constructor(name){
this.name = name;
}
}
const ann = new Person('Ann'); //creates an object { name: 'Ann' };
//ES5
const Person = function(name){
this.name = name;
}
const greg = new Person('Greg'); //creates an object { name: 'Greg' };
Not binding arguments
Arrow functions does not have own arguments
const myFunction = () => { console.log(arguments) };
myFunction(1, 'test'); //ReferenceError: arguments is not defined
const myOtherFunction = function{ console.log(arguments); }
myOtherFuncton(1, 'test'); // [1, 'test']
//the workaround for this is to use rest operator
const myFunc = (...args) => { console.log(args); }
myFunc(1, 'test'); // [1, 'test']
Not the best fit for method functions
Arrow functions that not have own this, so using this inside of arrow function will point to the parent object
const tom = {
name: 'Tom',
sayName: () => {
//this here points to global object - window
console.log(this.name); // will look for this.name on window.name and log undefined
}
};
tom.sayName();
//instead of arrow function you should use:
const tom = {
name: 'Tom',
sayName(){
//this here points to tom
console.log(this.name); // will log 'Tom'
}
};
tom.sayName();
No prototype
Arrow functions does not have prototype property
const Animal = () => {};
console.log(Animal.prototype); //undefined
No generators
Arrow functions cannot be used with yield keyword (except when permitted within functions further nested within it). As a consequence, arrow functions cannot be used as generators.
When to use arrow functions
- Use function keyword to decare functions in a global scope, for generators, constructors and object methods.
- Use function when you need to have an access to prototype
- If you more OOP person use new class syntax with constructor keywords
- Use arrow function in other cases
- https://developer.mozilla.org