Skip to content
Theory · Closures and this · lesson 1 of 11

Functions as values

What you'll learn

What you'll learn:

  • pass a function as an argument, store it in a variable or an object, and return it from another function;
  • explain what a closure is and why a variable lives on after its call ends;
  • predict what functions created in a loop with let and with var return;
  • tell what this is in a call, and give a method its object back with bind or an arrow function.
A card n * 10 is slotted into a machine mapAll, and tiles of one, two and three dots come out as 10 20 30

Picture a recipe card. You can cook the dish from it right now. But you can also hand the card to a friend, put it in a box with other recipes, or stick it on the fridge. Whoever ends up with the card cooks from it, whenever they need to.

A function in JavaScript is like such a card. A function's name without parentheses is the card itself, and parentheses after the name mean "cook it now". This card stays with us through every lesson of the theme.

As you already know, the map method takes a function as an argument and calls it on its own for each element of an array. You can write a function that works the same way as map yourself. Here mapAll does the same as map, but it takes the array as its first parameter:

JavaScript
function mapAll(nums, fn) {
    const result = [];
    for (const n of nums) {
        result.push(fn(n));
    }
    return result;
}

console.log(mapAll([1, 2, 3], (n) => n * 10)); // [ 10, 20, 30 ]
console.log(mapAll([1, 2, 3], (n) => n % 2 === 0)); // [ false, true, false ]

Let's go through the first call:

  1. mapAll gets the array [1, 2, 3] and the arrow function (n) => n * 10. The function sits in the parameter fn, like a card in your hand.
  2. The for…of loop takes the elements one by one.
  3. The call fn(n) runs the function passed in the same way a call by name does and returns its result.
  4. result.push collects the results into a new array, and the program prints [ 10, 20, 30 ].

Higher-order functions

The function mapAll takes another function. So, like forEach from the array-methods theme, it is a higher-order function. The arrow function passed to it is a callback.

The work here is split between two:

  • the higher-order function decides when and with which arguments to call the callback and what to do with its result;
  • the callback decides what to do with one element.

The loop that builds the new array is written in mapAll once. For another task only the callback changes. In the first call it multiplies the numbers by 10, in the second it checks whether they are even.

forEach, filter and reduce work the same way. The walk over the array is hidden inside the method, and the action comes from outside.

What else you can do with a function

A function is a value, the same as a number or a string. Since you can do with functions everything you do with other values, they are called first-class functions. Interviewers like to ask what it means that functions in JavaScript are first-class. The answer is three actions: a function can be passed as an argument, stored, and returned from another function. You have already seen passing as an argument, so two actions are left.

Storing

You can put a function in a constant, in an array element or in an object property, and call it from there. It is a card put away in a box: you can take it out at any moment.

Returning

A function can be returned from another function with return. Then the call gives back not a number or a string but a ready card. You can store it, or call it right away by putting a second pair of parentheses after the call.

Both actions are in one example:

JavaScript
function pick(sign) {
    if (sign === "+") {
        return (a, b) => a + b;
    }
    return (a, b) => a - b;
}

const ops = { plus: pick("+"), minus: pick("-") };
console.log(ops.plus(5, 3), ops.minus(5, 3)); // 8 2
console.log(pick("+")(2, 2)); // 4

Let's go step by step:

  1. pick returns not a number but a function: addition for "+" and subtraction for any other sign.
  2. const ops = { … } stores both functions in the properties plus and minus of the object ops.
  3. ops.plus(5, 3) takes the function out of the property plus and calls it, and the program prints 8 2.
  4. pick("+")(2, 2) first gets the addition function, and the second pair of parentheses calls it right away with two arguments. The result is 4.

Here the card analogy stops working: you give a paper card away, and you no longer have it. A function can be put in ten places at once, and all of them lead to one and the same function.

Common mistake

The function should return a function, but it returns the result of a call:

JavaScript
function double(n) {
    return n * 2;
}

function getDouble() {
    return double(); // ✗
}

const f = getDouble();
console.log(f(4));
TEXT
TypeError: f is not a function

The parentheses after double call it right in the return, with no argument, and the call gives NaN. So getDouble returns the number NaN, and a number cannot be called. It is like handing your friend a cooked dish instead of the card. To return the function itself, write its name without parentheses: return double;.

Key points

  • A function is a value: you pass it as an argument, keep it in a variable, an array or an object, and return it from another function.
  • A higher-order function takes or returns another function, and the function passed to it is a callback.
  • A name without parentheses is the function itself; a name with parentheses is its call and its result.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way