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
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.
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];
Array and returned.
f1() ,
f2() and
f3() should result in
1,
4,
9, but the actual result is:
##
f1(); // 16 f2(); // 16 f3(); // 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
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
and execute it immediately" is used here:
(function (x) { return x * x; })(3); // 9
function (x) { return x * x } (3);
Parsing problems will report a SyntaxError error, so the entire function definition needs to be enclosed in parentheses:
(function (x) { return x * x }) (3);
(function (x) { return x * x; })(3);
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
mechanism and only have functions, a private variable can also be encapsulated 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; } } }
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
, 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,我们可以利用闭包创建新的函数pow2
和pow3
:
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用函数来写这些计算。来试试:
'use strict'; // 定义数字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!