您的位置:首页 > 其它

closure

2016-05-14 10:19 232 查看
唉,大名鼎鼎的闭包

有些东西其实你一直在用,但如果有人突然把这个东西抽象成一个名词,然后加一堆你有点理解不了的定义,那么,你就成功的被忽悠了

'use strict';

function add( x,y ){
return function(){
return x + y;
}
}

var foo = add(1,2);
//  先声明一个foo,这个foo是什么呢?就是add函数return的function
//  foo = function(){
//      return 1 + 2;
//  }

foo();  // 执行 => 3


我对闭包最初的理解就是

一个函数,返回一个函数,想得到最终结果,赋值之后再执行

后来我发现,是的,还挺对,就这样

// 来自廖老师博客的求数组之和的例子

'use strict';

function sum(arr){
return function(){
return arr.reduce(function(x,y){
return x + y;
});
};
};
var foo = sum([1,2,3,4]);
foo();  //  10


看的时候一脸懵逼,怎么那么多return,我自己先简化一下

function sum(arr){
return function(){
// 返回arr数组元素之和
};
};


ok,和第一个例子形式一样了,舒服

循环

'use strict';

function tick( stop ){
for( var i=0; i<stop; i++ ){
setTimeout(function(){
console.log(i);
},i*1000);
}
}

tick(3);
// 每隔一秒
//  3
//  3
//  3


很奇怪,
i*1000
正常的执行了,但是
console.log(i)
却没有

因为setTimeout的函数里的i是整个函数的,延迟的时候,根本没有执行
console.log(i)
,他只是手里一直拿着这个函数,等过了一秒,执行,我要打印i这个变量。唉?
i
早就退出for循环增到3了,你还想要回已经过时的
i


为了对比的更清楚

'use strict';

function tick( stop ){
for( let i=0; i<stop; i++ ){
setTimeout(function(){
console.log(i);
},i*1000);
}
}
tick(3);
// 每隔一秒
//  0
//  1
//  2


继续《你不知道的JavaScript》书里 :

for循环头部的let声明会有一种特殊的行为,这个行为指出变量在循环过程中不止被声明一次,每次迭代都会声明。随后的每个迭代都会使用上一个迭代结束时的值来初始化这个变量

我的理解是:

let i=0
,在进入迭代后,把
0
赋值给
i
setTimeout()
的回调函数变成了
console.log(0);
至于为什么
let
就会赋值而
var
不赋值,因为
let
循环一次就死一次,不赋值的话let的出生也完全没意义

最后是书里的定义:

当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行,这时就产生了闭包
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数 闭包