SoFunction
Updated on 2025-04-07

JavaScript closure_Planning of the Power Node Java Academy

Function as return value

In addition to accepting functions as parameters, higher-order functions can also return functions as result values.

Let's achieve a rightArraysum of the Generally, the sum function is defined like this:

function sum(arr) {
  return (function (x, y) {
    return x + y;
  });
}

sum([1, 2, 3, 4, 5]); // 15

However, what if you don’t need to sum it immediately, but calculate it as needed in the subsequent code? You can not return the sum result, but return the sum function!

function lazy_sum(arr) {
  var sum = function () {
    return (function (x, y) {
      return x + y;
    });
  }
  return sum;
}

When we calllazy_sum()When , the result is not the summing result, but the summing function:

var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()

Only when the function f is called can the result of the sum be truly calculated:

f(); // 15

In this example, we are in the functionlazy_sumFunctions are defined insum, and, internal functionssumExternal functions can be referencedlazy_sumparameters and local variables, whenlazy_sumReturn functionsumWhen , the relevant parameters and variables are stored in the returned function. This program structure called "closure" has great power.

Please note that when we calllazy_sum()When each call returns a new function, even if the same parameter is passed in:

var f1 = lazy_sum([1, 2, 3, 4, 5]);
var f2 = lazy_sum([1, 2, 3, 4, 5]);
f1 === f2; // false

f1()andf2()The result of the call does not affect each other.

Closure

Notice that the returned function references local variables inside its definitionarr, so, when a function returns a function, the local variables inside it are also referenced by the new function, so the closure is simple to use and not easy to implement.

Another issue that needs to be noted is that the returned function is not executed immediately, but is not executed until f() is called. Let's take a look at an example:

function count() {
  var arr = [];
  for (var i=1; i<=3; i++) {
    (function () {
      return i * i;
    });
  }
  return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

In the example above, each loop, a new function is created, and then all the created 3 functions are added to oneArrayReturned.

You might think the callf1() f2()andf3()The result should be149, but the actual result is:

f1(); // 16
f2(); // 16
f3(); // 16

All are16! The reason is that the returned function refers to a variablei, but it is not executed immediately. When all three functions return, the variable i referenced has become4, so the final result is16

One thing to remember when returning a closure is: do not refer to any loop variables, or variables that will change later.

What if you have to refer to a loop variable? The method is to create another function and use the parameters of the function to bind the current value of the loop variable. Regardless of how the loop variable changes in the subsequent time, the value bound to the function parameter remains unchanged:

function count() {
  var arr = [];
  for (var i=1; i<=3; i++) {
    ((function (n) {
      return function () {
        return n * n;
      }
    })(i));
  }
  return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

f1(); // 1
f2(); // 4
f3(); // 9

Note that we use a syntax of "create an anonymous function and execute it immediately":

(function (x) {
  return x * x;
})(3); // 9

In theory, creating an anonymous function and executing it immediately can be written like this:

function (x) { return x * x } (3);

However, due to the problem of JavaScript syntax parsing, a SyntaxError error will be reported, so the entire function definition needs to be enclosed in brackets:

(function (x) { return x * x }) (3);

Usually, an anonymous function that is executed immediately can disassemble the function body, usually written like this:

(function (x) {
  return x * x;
})(3);

Having said so much, is it possible that the closure is to return a function and then delay execution?

Of course not! Closures have very powerful functions. Take a chestnut:

In object-oriented programming languages, such as Java and C++, to encapsulate a private variable inside the object, you can use private to modify a member variable.

In noclassMechanism, only in the language of function, can also encapsulate a private variable with the help of closures. We create a counter using JavaScript:

'use strict';

function create_counter(initial) {
  var x = initial || 0;
  return {
    inc: function () {
      x += 1;
      return x;
    }
  }
}

It works like this:

var c1 = create_counter();
(); // 1
(); // 2
(); // 3

var c2 = create_counter(10);
(); // 11
(); // 12
(); // 13

In the returned object, a closure is implemented, which carries local variablesx, and, variables cannot be accessed from external code at allx. In other words, a closure is a function that carries states, and its state can be completely hidden from the outside.

Closures can also turn multi-parameter functions into single-parameter functions. For example, to calculate xy, it can be used(x, y)Functions, but considering that x2 or x3 is often calculated, we can create new functions with closurespow2andpow3

function make_pow(n) {
  return function (x) {
    return (x, n);
  }
}

// Create two new functions:var pow2 = make_pow(2);
var pow3 = make_pow(3);

pow2(5); // 25
pow3(7); // 343

A big brain

A long time ago, there was a handsome guy named Alonzo Chiuqi. He found that he could use a computer to implement calculations only by using functions, but not by0、1、2、3These numbers and+、-、*、/These symbols.

JavaScript supports functions, so you can use JavaScript to write these calculations. Let's try:

'use strict';

// Define the number 0:var zero = function (f) {
  return function (x) {
    return x;
  }
};

// Define the number 1:var one = function (f) {
  return function (x) {
    return f(x);
  }
};

// Define addition:function add(n, m) {
  return function (f) {
    return function (x) {
      return m(f)(n(f)(x));
    }
  }
}