您的位置:首页 > Web前端 > JavaScript

JavaScript学习笔记十四:闭包

2016-06-30 14:19 585 查看
JavaScript教程传送门

函数作为返回值

高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。例如:一个返回求和函数的函数

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


闭包

当A函数的返回值是B函数时,A内部的局部变量还会被B函数引用,这里面会出现一个问题:

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


全部都是
16
!原因就在于返回的函数引用了变量
i
,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了
4
,因此最终结果为
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


闭包的使用场景

闭包可以作为一个携带状态的函数,并且它的状态可以完全对外隐藏起来:

'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


闭包还可以把多参数的函数变成单参数的函数。例如,要计算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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 闭包