# 闭包

## 函数作为返回值

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

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

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

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

``````f(); // 15
``````

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

`f1()``f2()`的调用结果互不影响。

## 闭包

``````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];
``````

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

``````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
``````

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

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

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

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

``````'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
``````

``````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
``````

## 脑洞大开

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);
}
};

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

// 计算数字2 = 1 + 1:

// 计算数字3 = 1 + 2:

// 计算数字5 = 2 + 3:

// 你说它是3就是3，你说它是5就是5，你怎么证明？

// 呵呵，看这里:

// 给3传一个函数,会打印3次:
(three(function () {
console.log('print 3 times');
}))();

// 给5传一个函数,会打印5次:
(five(function () {
console.log('print 5 times');
}))();

// 继续接着玩一会...
``````