Home >Web Front-end >JS Tutorial >How to use closures in js?

How to use closures in js?

零下一度
零下一度Original
2017-06-28 13:38:101613browse

This article mainly introduces JavaScript closures. Closures are a difficulty and feature of the JavaScript language. Many advanced applications rely on closures to implement

functions as return values

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

Let’s implement a summation of Array. Normally, the summation function is defined like this:


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

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

However, if there is no need to sum immediately, but in the following code, according to What should I do if I need to calculate again? Instead of returning the summation result, you can return the summation function!


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

When we call lazy_sum(), what is returned is not the summation result, but the summation function:


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

The result of the sum is actually calculated when function f is called:


f(); // 15

In this In the example, we define function sum in function lazy_sum, and internal functionsum can reference external function The parameters and local variables of lazy_sum, when lazy_sum returns the function sum, the relevant parameters and variables are saved in the returned function, this is called "Closure" )" program structure has great power.

Please note that when we call lazy_sum(), each call will return a new function, even if the same parameters are passed in:
## The calling results of


#

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

f1() and f2() do not affect each other.

Closure

Notice that the returned function references the local variable

arr inside its definition, so when After a function returns a function, its internal local variables are still referenced by the new function. Therefore, closures are easy to use but not easy to implement.

Another issue that needs attention 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++) {
    arr.push(function () {
      return i * i;
    });
  }
  return arr;
}

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

In the above example, a new function is created every time it loops, and then the 3 created functions are The functions are added to an

Array and returned.

You might think that calling

f1() , f2() and f3() should result in 1, 4, 9, but the actual result is:

##

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

all are

16

! The reason is that the returned function refers to the variable i, but it is not executed immediately. By the time all three functions return, the variable i they refer to has become 4, so the final result is 16.
One thing to keep in mind when returning a closure is: the return function should not reference any loop variables, or variables that will change subsequently.


What if you must reference the loop variable? The method is to create another function and use the

function parameters

to bind the current value of the loop variable. No matter how the loop variable changes subsequently, the value bound to the function parameter will remain unchanged. :

function count() {
  var arr = [];
  for (var i=1; i<=3; i++) {
    arr.push((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 the syntax of "create an

anonymous function

and execute it immediately" is used here:

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

Theoretically, to create an anonymous function and execute it immediately, you can write:


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

But because

JavaScript Grammar

Parsing problems will report a SyntaxError error, so the entire function definition needs to be enclosed in parentheses:

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

Usually, one is executed immediately The anonymous function can separate the function body, which is usually written like this:


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

Having said so much, is the purpose of closures to return a function and then delay execution? ?


of course not! Closures are very powerful. For example:


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


In languages ​​that do not have a

class

mechanism and only have functions, a private variable can also be encapsulated with the help of closures. We create a counter using JavaScript:

&#39;use strict&#39;;

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

It works like this:


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

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

In the returned object, a closure is implemented, which carries the local variable

x

, and the variable x cannot be accessed from external code at all. In other words, a closure is a function that carries state, and its state can be completely hidden from the outside world.

闭包还可以把多参数的函数变成单参数的函数。例如,要计算xy可以用Math.pow(x, y)函数,不过考虑到经常计算x2或x3,我们可以利用闭包创建新的函数pow2pow3


function make_pow(n) {
  return function (x) {
    return Math.pow(x, n);
  }
}

// 创建两个新函数:
var pow2 = make_pow(2);
var pow3 = make_pow(3);

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

脑洞大开

很久很久以前,有个叫阿隆佐·邱奇的帅哥,发现只需要用函数,就可以用计算机实现运算,而不需要0、1、2、3这些数字和+、-、*、/这些符号。

JavaScript支持函数,所以可以用JavaScript用函数来写这些计算。来试试:


&#39;use strict&#39;;

// 定义数字0:
var zero = function (f) {
  return function (x) {
    return x;
  }
};

// 定义数字1:
var one = function (f) {
  return function (x) {
    return f(x);
  }
};

// 定义加法:
function add(n, m) {
  return function (f) {
    return function (x) {
      return m(f)(n(f)(x));
    }
  }
}

The above is the detailed content of How to use closures in js?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn