closure

函数作为返回值

高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回.
我们来实现一个array的求.通常情况系啊,求和的函数是这样定义:

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

当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:

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

调用函数f时,才真正计算求和的结果:

f();//15

在这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时候,相关参数和变量都保存在返回的函数中,这种成为闭包.的程序结构拥有极大的威力;
请再注意一点,当我我们调用lay_sum()时,每次调用都会返回一个新的 函数,即使传入相同的参数:

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

f1()和f2的调用结果互不影响.

闭包

注意到返回的函数在其定义内部引用了局部变量arr,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易.
另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用到f()才执行,看个例子:

function count(){
var arr =[];
fot(var i=1;i<=3;i++){
app.push(function(){
return i*i;
})
return arr;
}
}
var results = count();
var f1 =results[0];
var f2 =results[1];
var f3 =results[2];

在上面的例子中,每次循环,都穿件一个新的函数,然后把创建的3个函数都添加到一个array中返回了
你可能认为调用f1(),f2()和f3()结果应该是1,4,9但实际结果是.

f1(); //16

f2(); //16

f3(); //16

全部都是16! 原因就在于返回的函数引用了变量i;但他并非立即执行,等到3个函数都返回时,
等到3个函数都返回时,它们所引用的变量i已经变成了4,因此最终结果为16;
返回闭包时 牢记的一点就是:返回函数不要引用任何循环变量. 或者后续会发生变化的变量.

如果一定要要引用循环变量怎么办?方式再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变;