The arrow function allows declaration of anonymous functions (lambda) in a more concise way. Let’s see what’s so great about it :).
Usage
const sayHello = (name) => console.log(`Hello ${name}`)
sayHello("World")
In ES5, this would be a bit more verbose.
var sayHello = function(name) {
console.log("Hello " + name)
}
sayHello("World")
Single argument
When only one parameter is required, the arrow function can be written without the brackets for the parameter like this:
const sayHello = name => console.log(`Hello ${name}`)
sayHello("World")
Although I much prefer keeping consistency by always having the brackets to indicate that they are parameters.
Much like in C#, the arrow function can be expression or block bodied.
Expression bodied arrow function means implicit return
Expression bodied arrow function implicitly returns a value.
So, as an example:
const add = (num1, num2) => num1 + num2
let result = add(2,3)
console.log(result)
is functionally the same as:
const add = (num1, num2) => {
return num1 + num2
}
let result = add(2,3)
console.log(result)
When writing functions in functional style, it is preferred to write expression bodied functions because of the implicit return. The reason for this is simple – in functional programming, we always expect an output from a function.
Block bodied arrow function
When you’re wanting to simply declare a function as normal with the arrow function, you can use a block bodied arrow function – this allows you to declare a function as you would with a conventional function.
“this” Behaves Differently
this
in an Arrow function
is always lexically scoped – this means that this
will always be what you expect it to be.
Let’s have a look an example to get a better understanding of how this
behaves in a conventional function
over arrow function
.
class Hello {
constructor(name) {
this.name = name
}
changeName = (name) => {
this.name = name
}
sayHelloArrow = () => {
console.log(`hello ${this.name}`)
}
sayHelloFunction() {
console.log(`hello ${this.name}`)
}
}
let bryan = new Hello('Bryan');
bryan.sayHelloArrow() // hello Bryan
bryan.sayHelloFunction() // hello Bryan
let kevin = { name: 'Kevin' }
bryan.sayHelloFunction.call(kevin) // Hello Kevin
bryan.sayHelloArrow.call(kevin) // Hello Bryan
One of the most common mistakes that you’ll come across in JavaScript is the usage of setTimeout
for waiting for some external script to load asynchronously. Here’s a simplified example of this mistake:
var scriptHasLoaded = false
setTimeout(function() {
scriptHasLoaded = true
}, 1000)
function MyClass(name) {
this.name = name
function sayMyName() {
console.log(this.name)
}
this.sayName = function() {
if(scriptHasLoaded) {
sayMyName()
} else {
setTimeout(this.sayName, 100)
}
}
}
var myObj = new MyClass('Bruce')
myObj.sayName() // Does not print name
Because window.setTimeout
changes this
, we usually have to have some workaround in place by capturing the object
that we are referring to, in most cases, the actual object
enclosing our function
.
var scriptHasLoaded = false
setTimeout(function() {
scriptHasLoaded = true
}, 1000)
function MyClass(name) {
var _this = this; // reference to `this`
this.name = name
function sayMyName() {
console.log(_this.name) // we use it everywhere where we want lexical `this`
}
this.sayName = function() {
if(scriptHasLoaded) {
sayMyName()
} else {
setTimeout(_this.sayName, 100) // here too
}
}
}
var myObj = new MyClass('Bruce')
myObj.sayName()
That’s quite a few things to remember to try and avoid the mistake. Now let’s see how this can be simplified using ES6’s arrow function
:
var scriptHasLoaded = false
setTimeout(function() {
scriptHasLoaded = true
}, 1000)
function MyClass(name) {
this.name = name
var sayMyName = () => {
console.log(this.name)
}
this.sayName = () => {
if(scriptHasLoaded) {
sayMyName()
} else {
setTimeout(() => { this.sayName() }, 100)
}
}
}
var myObj = new MyClass('Bruce')
myObj.sayName()
So, what’s the usecase for the arrow function
? Well, anywhere where you’re not depending on this
to be change during runtime as it’s a more concise way of declaring a function, without the possibility of this
changing to other values.