In order to understand arrow function syntax, we should start by refactoring a regular function step by step:
function square(a) {
return a * a;
}
We can start by refactoring the function declaration to use a variable assignment:
const square = function (a) {
return a * a;
}
Then, we can refactor the regular function
to an arrow
function:
const square = (a) => {
return a * a;
}
If there’s only one argument, we can omit the parentheses around it:
const square = a => {
return a * a;
}
If the function is a single expression, you can omit the curly braces and
return
statement and use an implicit return:
const square = a => a * a;
The main difference between arrow functions and regular functions is
execution context (i.e. the value of this
). Technically
speaking, most other differences often mentioned either stem from this one
or are side effects of it.
In a regular function, this
is dynamic and depends on how the
function was invoked:
function simple() { return this; }
const object = {
method() { return this; }
;
}class Class {
classMethod() { console.log(this); }
}const instance = new Class();
simple(); // `this` refers to the global object
new simple(); // `this` refers to the newly created instance
.method(); // `this` refers to `object`
object.call(object); // `this` refers to `object`
simple
.classMethod(); // `this` refers to `instance`
instancesetTimeout(
.classMethod, 0 // `this` refers to the global object
instance; )
Arrow functions, unlike regular ones, don’t define their own execution
context therefore this
inside an arrow function always refers
to the lexical this
(i.e. the scope in which the arrow
function was defined).
const simple = () => this;
const object = {
method: () => this
;
}class Class {
= () => { console.log(this); }
classMethod
}const instance = new Class();
simple(); // `this` refers to the global object
new simple(); // Uncaught TypeError: simple is not a constructor
.method(); // `this` refers to the global object
object.call(object); // `this` refers to the global object
simple
.classMethod(); // `this` refers to `instance`
instancesetTimeout(
.classMethod, 0 // `this` refers to `instance`
instance; )
As you can see from these examples, there’s a difference in how
constructors work due to the execution context and how it’s resolved.
Regular functions can be used as constructors in contrast to arrow
functions which will throw a TypeError
instead.
Moreover, arrow functions and regular functions present some differences
when used to define class methods. A regular function method will end up
with a different execution context when passed as a callback. This can be
handled using Function.prototype.bind()
or by using an arrow
function which doesn’t have this issue.
If you want to read more about the this
keyword, you should
check out our
previous article on the subject.