Lesson guide

Learning objectives

  • Explain the main purpose of Arrow functions revisited in JavaScript.
  • Identify the syntax, APIs, or concepts introduced in this lesson.
  • Use the examples to predict how JavaScript will behave before you run similar code.
  • Connect this topic to nearby lessons in Advanced working with functions.

Real-world context

This lesson matters when you need to recognize where Arrow functions revisited fits into real JavaScript programs. Let’s revisit arrow functions.

Key ideas

  • Arrow functions revisited is part of the Advanced working with functions chapter, so it builds on the surrounding concepts rather than standing alone.
  • Read each code example in two passes: first for the result, then for the rule that explains the result.
  • When a section compares similar features, focus on the condition that makes you choose one feature over another.

Key terms

  • Arrow functions revisited
  • Arrow
  • functions
  • revisited
  • Advanced working with functions

Let’s revisit arrow functions.

Arrow functions are not just a “shorthand” for writing small stuff. They have some very specific and useful features.

JavaScript is full of situations where we need to write a small function that’s executed somewhere else.

For instance:

  • arr.forEach(func)func is executed by forEach for every array item.
  • setTimeout(func)func is executed by the built-in scheduler.
  • …there are more.

It’s in the very spirit of JavaScript to create a function and pass it somewhere.

And in such functions we usually don’t want to leave the current context. That’s where arrow functions come in handy.

Arrow functions have no “this”

As we remember from the chapter Object methods, "this", arrow functions do not have this. If this is accessed, it is taken from the outside.

For instance, we can use it to iterate inside an object method:

javascript
let group = {
  title: "Our Group",
  students: ["John", "Pete", "Alice"],

  showList() {
    this.students.forEach(
      student => alert(this.title + ': ' + student)
    );
  }
};

group.showList();

Here in forEach, the arrow function is used, so this.title in it is exactly the same as in the outer method showList. That is: group.title.

If we used a “regular” function, there would be an error:

javascript
let group = {
  title: "Our Group",
  students: ["John", "Pete", "Alice"],

  showList() {
    this.students.forEach(function(student) {
      // Error: Cannot read property 'title' of undefined
      alert(this.title + ': ' + student);
    });
  }
};

group.showList();

The error occurs because forEach runs functions with this=undefined by default, so the attempt to access undefined.title is made.

That doesn’t affect arrow functions, because they just don’t have this.

Arrow functions can’t run with new

Not having this naturally means another limitation: arrow functions can’t be used as constructors. They can’t be called with new.

Arrow functions VS bind

There’s a subtle difference between an arrow function => and a regular function called with .bind(this):

  • .bind(this) creates a “bound version” of the function.
  • The arrow => doesn’t create any binding. The function simply doesn’t have this. The lookup of this is made exactly the same way as a regular variable search: in the outer lexical environment.

Arrows have no “arguments”

Arrow functions also have no arguments variable.

That’s great for decorators, when we need to forward a call with the current this and arguments.

For instance, defer(f, ms) gets a function and returns a wrapper around it that delays the call by ms milliseconds:

javascript
function defer(f, ms) {
  return function() {
    setTimeout(() => f.apply(this, arguments), ms);
  };
}

function sayHi(who) {
  alert('Hello, ' + who);
}

let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // Hello, John after 2 seconds

The same without an arrow function would look like:

javascript
function defer(f, ms) {
  return function(...args) {
    let ctx = this;
    setTimeout(function() {
      return f.apply(ctx, args);
    }, ms);
  };
}

Here we had to create additional variables args and ctx so that the function inside setTimeout could take them.

Common mistakes

  • Skipping the small examples and then missing the exact rule that Arrow functions revisited depends on.
  • Copying code without changing one value at a time to see which part controls the result.
  • Treating similar-looking syntax or APIs as interchangeable before checking their edge cases.

Summary

Arrow functions:

  • Do not have this
  • Do not have arguments
  • Can’t be called with new
  • They also don’t have super, but we didn’t study it yet. We will on the chapter Class inheritance

That’s because they are meant for short pieces of code that do not have their own “context”, but rather work in the current one. And they really shine in that use case.

Predict

Before running this arrow-function check, predict the five output lines. It covers lexical this, regular callback thisArg, missing arguments, and the constructor limitation.

javascript
Reveal explanation

The output is Team:Ada|Team:Lin, Other:Ada|Other:Lin, Team:hi:Ada,Lin, outer, and TypeError. The arrow callback in showWithArrow has no own this, so it uses the method’s this, which is group. The regular callback can receive a separate thisArg, so it uses { title: "Other" }. The arrow returned by makeLabel also keeps group as this. Arrows have no own arguments, so outerArgument's arrow reads the outer function’s first argument, not "inner". Arrow functions cannot be called with new.

Try it

Replace the arrow in showWithArrow with function(student) { return ... } and remove the thisArg; predict why this.title no longer reads group.title.

Practice

  • Rewrite one example from this lesson without looking at the original, then run it and compare the result.
  • Change one input, operator, method call, or option in a code sample and predict what will happen before running it.
  • Explain Arrow functions revisited in your own words as if you were reviewing it with another learner.

Keep learning

Continue with Property flags and descriptors when you are ready for the next lesson.