闭包理解

如何在外部引用一个函数内部的变量?
//===============================
function a(){
var i = 1;
}
alert(i); //undifined
//===============================
为什么这样?因为一个变量的作用域只在一个函数本身,这是javascript最基本的入门的概念,想来不用多说。

//===============================
function a(){
var i=0;
function b(){
alert(++i); 
}
return b;
}

var c = a();
c(); //1; 
//===============================
这个例子来自于百度百科,有两个关键点
1. b是定义在a的内部
2. a的运行结果是 return b。此时b就一直保存在内存当中,直到你手动删除为止。
3. b引用了a的变量(这一点极其重要)。

所以,c = a();其实调用的就是b,由于b是在a的内部,所以就可以访问i(这是javascript的链接作用域(chain scope),内部函数可以访问外部函数的变量)。
这样,就达到了在a的外部,调用a中的变量。

再有,a中定义的函数是b,而不是一个匿名函数,但是这样是可行的。所以,上面第4条的定义就是错的,闭包并不一定是一个匿名函数。

这一个例子,基本就已经说完了闭包了。但是看的人可能还是没有一个明确的概念,那么就继续看几个例子。

//===============================
function a(){
var i = 1;
function b(){
alert(i);
}
i++;
return b;
}
var f = a();
f(); // 2

为什么呢是2呢?
return b是在a的最后执行,所以,在ruturn b的时候,已经将a中代码全部执行了,所以 i=2;若在i++前返回b。f()的结果就是1。这就可以推出:也可以把 var i = 1;写在function b的后面。只要写在return之前即可。

function a(){
var i = 1;
function b(){alert(i)}
return b;
i++;
}
//===============================

//===============================
function a(){
var i = 1;
b = function(){alert(i)}
c = function(){i++}
d = function(j){i = j}
}
a(); //运行一次a,为b\c\d赋值。

b(); // 1
c(); // i++
b(); // 2

d(3); // i = 3
b(); //3

此处应有三点需要说明:
1. 在函数内部定义变量一定要用var,否则定义的就是一个全局变量。在这里b c d皆没有用var,所以就可以在外部直接调用这三个全局变量
2. a需要运行一次,才会给bcd赋值。否则会报错 b c d未定义
3. b c d 都在a内,所以都可以调用变量i.
//===============================

循环中的闭包

//=============================== 
function closureInLoop(Ar){
var result = [];
for(var i=0;i<Ar.length;i++){
var item = ‘item‘ + Ar[i];
result.push(function(){alert(item + ‘ ‘ + Ar[i])});

return result; 
}

function test(){
var fnList = closureInLoop([1,2,3]);
alert(fnList);
for(var j=0;j<fnList.length;j++){
fnList[j]();
}
}
test(); // item3 undifined(3次);

我原以为,会依然出现item 1,item 2,item 3。结果却不同,这是什么原因?
先把fnList输出来看看[fnction(){alert(item + ‘ ‘ + Ar[i])},function(){alert(item + ‘ ‘ + Ar[i])},function(){alert(item + ‘ ‘ + Ar[i])},]
三个一模一样的function,都是调用的Ar[i]。此时i是多少呢?看下前面的closureInLoop的for循环。
传入的参数是[1,2,3],所以closureInLoop中的Ar.length就是3。所以for执行完的时候:
i=3;
item = ‘item‘ + Ar[2];也就是item3;

由于return result了。所以此时resulte里面的function就形成了闭包。
三个function都引用了i和item。此时i=3,item = item3;
所以都是function(){item + ‘ ‘ + Ar[3]}
但是Ar传入的是[1,2,3],Ar.length = 3 没错。
但是Ar[0] = 1;Ar[1] = 2; Ar[2] = 3....都没错。

但是骚年们,Ar[3] = undifined;
alert(item + ‘ ‘ + Ar[3]) = item3 undifined。

Over,这个太麻烦,我想也没几个人这样写吧。不过这个例子非常经典,可以仔细看看。

例外一种循环里的闭包

for(var i=0;i<10;i++){
setTimeout(function(){
console.log(i);
},1000);
}
这样并不能依次输出i,而是输出10次10。
//===================================

每次都创建一个新的闭包

//===================================
function createClosure(number,reference){
var num = number,
ref = reference,
anArray = [1,2,3];
return function(x){
num += x;
anArray.push(num);
alert(num + ‘ ‘ + anArray.toString() + ‘ ‘ + ref);
}
}
closure_1 = createClosure(20,‘ref_1‘);
closure_1(10); //30 [1,2,3,30] ref_1

closure_2 = createClosure(100,‘ref_2‘);
closure_2(-10); //90 [1,2,3,90] ref_2

说好的闭包呢,为什么没有继续用closure_1的nunber和reference?

因为我们每建立一个新的闭包,都重新将number和reference的通过参数改变。
//===============================

参考资料

http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
http://jibbering.com/faq/notes/closures/
http://en.wikipedia.org/wiki/Closure_(computer_programming)
http://baike.baidu.com/view/648413.htm
http://coolshell.cn/articles/6731.html
http://bonsaiden.github.io/JavaScript-Garden/zh/

时间: 2024-10-05 05:37:02

闭包理解的相关文章

JS闭包理解

Js闭包理解 在很多面试题中都会问什么是js的闭包,为什么需要使用闭包,使用闭包的优缺点! 我在面试其他人的时候也喜欢问这个问题,回答的也是千奇百怪,现在就总结一下我对闭包的理解. 闭包是一种概念,这种概念比较复杂,很多地方的定义不尽相同,我的理解是:闭包是能读取函数内部变量的函数,也就是定义在函数内部的函数,成为函数内部元素与外部沟通的桥梁. 闭包的概念是有js的链式作用域引出来的,所谓链式作用域就是指:内部函数可以读取到所有的外部变量,而外部变量或者函数不能读取到函数的内部变量,变量的作用域

javascript之闭包理解以及应用场景

之前读了js权威指南,也写了篇博文,但是实话实说当初看闭包确实还是一头雾水.现在时隔一个多月(当然这一段时间还是一直有在看闭包的相关知识)理解就更深入了一点,下面说说我的理解. 1 function fn(){ 2 var a = 0; 3 return function (){ 4 return ++a; 5 } 6 } 如上所示,上面第一个return返回的就是一个闭包,那么本质上说闭包就是一个函数.那么返回这个函数有什么用呢? 那是因为这个函数可以调用到它外部的a这个变量.其实也就是说,r

JS闭包理解_摘

原文地址1:http://www.cnblogs.com/mzwr1982/archive/2012/05/20/2509295.html 闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的理解以及js内部解释器的运作方式的描述,都是可以看出你js实际水平的.即使你没答对,也能让考官对你的水平有个评估.那么我先来说说我对js中的闭包的理解. 闭包是

JavaScript的闭包理解

由于本人是做java web 开发的,对js只是存在很浅的理解,js闭包的概念很早就听说了,但是一直都不明白是什么意思,今天准备梳理一下闭关的概念; 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收 闭包的定义及其优缺点 闭包 是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个

javascript 之闭包-理解不了来找我

1,闭包是什么 (百度百科定义)--闭包是可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变 量).“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境 (作用域). W3C ECMAScript在闭包的解释中,有这么一句话:闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量

关于javascript闭包理解

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一:关于变量的作用域 Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. function f1(){ var n=999; } alert(n); // error 声明变量的时候记得使用var声明,不然的话java

js中的闭包理解

闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的理解以及js内部解释器的运作方式的描述,都是可以看出你js实际水平的.即使你没答对,也能让考官对你的水平有个评估.那么我先来说说我对js中的闭包的理解. 闭包是很多语言都具备的特性,在js中,闭包主要涉及到js的几个其他的特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等. 在理解闭包以前.最好能

js 闭包 理解 copy

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外

JavaScript ——闭包理解

昨天晚上听别人谈起闭包这个东西,虽然对js有一点了解但却丝毫没有印象,今天也没什么事就顺便研究了一下满足好奇宝宝.整合于网上的理解,记录一下. 一.闭包的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 全局作用域 局部作用域 :一个 function 形成一个独立的作用域, 而且方法作用域还能够嵌套. 与别的语言不同的是: 花括号({})不能形成一个独立的作用域, 例如Java中的作用域. 下面我们举例说说作用域 1 var m = 1; 2 function f(){

js中的闭包理解一

闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的理解以及js内部解释器的运作方式的描述,都是可以看出你js实际水平的.即使你没答对,也能让考官对你的水平有个评估.那么我先来说说我对js中的闭包的理解. 闭包是很多语言都具备的特性,在js中,闭包主要涉及到js的几个其他的特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等. 在理解闭包以前.最好能