DEV Community

Cover image for Arrow functions & this keyword

Arrow functions & this keyword

We learned about arrow functions and the this keyword in previous blog posts. Now we will combine the two and see how arrow functions behave differently compared to standard function expressions.

Arrow functions, for the most part, work like function expressions with a concise syntax. The critical difference is that arrow functions do not have their bindings to this keyword.

For a function expression, this changes based on the context a function is called in. For arrow functions, this is based on the enclosing lexical scope. Arrow functions follow normal variable lookup. They look for this in the current scope, and if not found, they move to the enclosing scope.

We will use the same scenarios as the previous blog post.

  1. By itself.
  2. When used in a constructor.
  3. Called as a method of the object.
  4. In the case of strict mode.
  5. In an event.

Let us use arrow functions in the above five examples and see how they behave:

By itself

const foo = () => {
    return this;
}

console.log(foo()); // window or global object

Exactly same as function expressions.

When used in a constructor.

const Order = (main, side, dessert) => {
    this.main = main;
    this.side = side;
    this.dessert = dessert;
    this.order = function () {
        return `I will have ${this.main} with ${this.side} and finish off with a ${this.dessert}`;
    }
}
const newOrder = new Order("sushi", "soup", "yogurt"); // Order is not a constructor

console.log(newOrder.order());

Arrow functions cannot be used as constructors. They differ in this case. Although changing the this.order to an arrow function would work the same if we did not use the arrow function as a constructor.

function Order(main, side, dessert) {
    this.main = main;
    this.side = side;
    this.dessert = dessert;
    this.order = () => {
        return `I will have ${ this.main } with ${ this.side } and finish off with a ${ this.dessert } `;
    }
}
const newOrder = new Order("sushi", "soup", "yogurt");

console.log(newOrder.order());
// I will have sushi with soup and finish off with a yogurt

Called as a method of the object.

const myObject = {
    main: "butter chicken",
    side: "rice",
    dessert: "ice cream",
    order: () => {
        return `I will have ${this.main} with ${this.side} and finish off with ${this.dessert}`;
    }
}

console.log(myObject.order());
// I will have undefined with undefined and finish off with undefined

Does not work at all like function expressions!. Arrow functions are not direct replacements of function expressions when used as methods of an object.

Why did it provide undefined for the variables main, side, and dessert? The this within the arrow function is the one that was current where we defined the object myObject (in this example window). The window does not have the three variables order is looking for.

In the case of strict mode.

"use strict";
const foo = () => {
    return this;
};

console.log(foo() === undefined); // false
console.log(foo()); // window or global object

Does not work at all like function expressions! because the rules of lexical this take precedence over strict-mode this rules.

In an event.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta content="utf-8" http-equiv="encoding">
</head>
<body>
    <button id="mybutton">
        Click me!
    </button>
    <script>
        var element = document.querySelector("#mybutton");
        element.addEventListener('click', (event) => {
            console.log(this); // window object
            console.log(this.id); // undefined
        }, false);
    </script>
</body>
</html>

Does not work at all like function expressions! The value of this inside an arrow function is determined by where the arrow function is defined, not where it is used. In this example, we can access the element using event.currentTarget. We can read more here.

Summary: Except when using it on its own, arrow function behaves differently compared to function expressions. They are concise and provide advantages but do know when not to use them as a direct replacement of function expressions.

Top comments (0)