`
liudaoru
  • 浏览: 1557861 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

在Javascript中,什么是闭包(Closure)

    博客分类:
  • Ajax
阅读更多

from: http://javascript.chinahtml.com/2006/javascript-11607091807203.shtml

 

闭包的两个特点:

1、作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态。
2、一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

例1。

<script type="text/javascript"> 
function sayHello2(name) { 
 var text = 'Hello ' + name; // local variable 
 var sayAlert = function() { alert(text); } 
 return sayAlert; 

var sy = sayHello2('never-online'); 
sy(); 
</script>

作为一个Javascript程序员,应该明白上面的代码就是一个函数的引用。如果你还不明白或者不清楚的话,请先了解一些基本的知识,我这里不再叙述。

上面的代码为什么是一个闭包?
因为sayHello2函数里有一个内嵌匿名函数
sayAlert = function(){ alert(text); }
在Javascript里。如果你创建了一个内嵌函数(如上例),也就是创建了一个闭包。

在C或者其它的主流语言中,当一个函数返回后,所有的局部变量将不可访问,因为它们所在的栈已经被消毁。但在Javascript里,如果你声明了一个内嵌函数,局部变量将在函数返回后依然可访问。比如上例中的变量sy,就是引用内嵌函数中的匿名函数function(){ alert(text); },可以把上例改成这样:
<script type="text/javascript"> 
function sayHello2(name) { 
 var text = 'Hello ' + name; // local variable 
 var sayAlert = function() { alert(text); } 
 return sayAlert; 

var sy = sayHello2('never-online'); 
alert(sy.toString()); 
</script>
这里也就与闭包的第二个特点相吻合。

例2。
<script type="text/javascript"> 
function say667() { 
 // Local variable that ends up within closure 
 var num = 666; 
 var sayAlert = function() { alert(num); } 
 num++; 
 return sayAlert; 


var sy = say667(); 
sy(); 
alert(sy.toString()); 
</script>

上面的代码中,匿名变量function() { alert(num); }中的num,并不是被拷贝,而是继续引用外函数定义的局部变量——num中的值,直到外函数say667()返回。

例3。
<script type="text/javascript"> 
function setupSomeGlobals() { 
 // Local variable that ends up within closure 
 var num = 666; 
 // Store some references to functions as global variables 
 gAlertNumber = function() { alert(num); } 
 gIncreaseNumber = function() { num++; } 
 gSetNumber = function(x) { num = x; } 


</script> 
<button onclick="setupSomeGlobals()">生成 - setupSomeGlobals()</button> 
<button onclick="gAlertNumber()">输出值 - gAlertNumber()</button> 
<button onclick="gIncreaseNumber()">增加 - gIncreaseNumber()</button> 
<button onclick="gSetNumber(5)">赋值5 - gSetNumber(5)</button>

上例中,gAlertNumber, gIncreaseNumber, gSetNumber都是同一个闭包的引用,setupSomeGlobals(),因为他们声明都是通过同一个全局调用——setupSomeGlobals()。
你可以通过“生成”,“增加”,“赋值”,“输出值”这三个按扭来查看输出结果。如果你点击“生成”按钮,将创建一个新闭包。也就会重写gAlertNumber(), gIncreaseNumber(), gSetNumber(5)这三个函数。

如果理解以上代码后,看下面的例子:

例4。
<script type="text/javascript"> 
function buildList(list) { 
 var result = []; 
 for (var i = 0; i < list.length; i++) { 
 var item = 'item' + list[i]; 
 result.push( function() {alert(item + ' ' + list[i])} ); 
 } 
 return result; 


function testList() { 
 var fnlist = buildList([1,2,3]); 
 // using j only to help prevent confusion - could use i 
 for (var j = 0; j < fnlist.length; j++) { 
 fnlist[j](); 
 } 


testList(); 
</script> 
运行结果: 
item 3 is undefined 
item 3 is undefined 
item 3 is undefined 

代码result.push( function() {alert(item + ' ' + list[i])} ), 
使result数组添加了三个匿名函数的引用。这句代码也可以写成 
var p = function() {alert(item + ' ' + list[i])}; 
result.push(p);


关于为什么会输出三次都是 "item 3 is undefined"

在上面的例子say667()例子中已经解释过了。
匿名函数function() {alert(item + ' ' + list[i])}中的list[i]并不是经过拷贝,而是对参数list的一个引用。直到函数buildList()返回为止,也就是说,返回最后一个引用。即遍历完list(注:list的最大下标应该是2)后,经过i++也就变成了3,这也就是为什么是item 3,而list[3]本身是没有初始化的,自然也就是undefined了。

例5。
<script type="text/javascript"> 
function newClosure(someNum, someRef) { 
 // Local variables that end up within closure 
 var num = someNum; 
 var anArray = [1,2,3]; 
 var ref = someRef; 
 return function(x) { 
 num += x; 
 anArray.push(num); 
 alert('num: ' + num +  
 'nanArray ' + anArray.toString() +  
 'nref.someVar ' + ref.someVar); 
 } 

var closure1 = newClosure(40, {someVar:' never-online'}) 
var closure2 = newClosure(99, {someVar:' BlueDestiny'}) 
closure1(4) 
closure2(3) 
</script>


在这最后一个例子中,展示如何声明两个不同的闭包。

分享到:
评论

相关推荐

    JavaScript闭包(closure).pdf

    JavaScript闭包(closure).pdf

    理解javascript函数式编程中的闭包(closure)_.docx

    理解javascript函数式编程中的闭包(closure)_.docx

    javascript闭包详解中文word版

    资源名称:javascript闭包详解 中文word版   内容简介: Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态语言C/C 的程序员来说是一个新的...

    javascript 闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

    JavaScript中的闭包(Closure)详细介绍

    主要介绍了JavaScript中的闭包(Closure)详细介绍,函数调用对象与变量的作用域链、什么是闭包等内容,并给出了实例,需要的朋友可以参考下

    JavaScript闭包

    Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态...本文将以例子入手来介绍Javascript闭包的语言特性,并结合一点 ECMAScript语言规范来使读者可以更深入的理解闭包。

    javascript中闭包(Closure)详解

    闭包(closure)是Javascript语言的一个...小编之前一直糊里糊涂的,没有能够弄明白JavaScript的闭包到底是什么,有什么用,本文把自己的理解些出来分享一下,希望不理解JavaScript闭包的朋友们看了之后能够理解闭包!

    理解javascript函数式编程中的闭包(closure)

    闭包(closure)是函数式编程中的概念,出现于 20 世纪 60 年代,最早实现闭包的语言是 Scheme,它是 LISP 的一种方言。之后闭包特性被其他语言广泛吸纳。 闭包的严格定义是“由函数(环境)及其封闭的自由变量组成...

    Javascript闭包(Closure)详解

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

    JavaScript知识点总结(十六)之Javascript闭包(Closure)代码详解

    很早就接触过闭包这个概念了,但是一直糊里糊涂的,没有能够弄明白JavaScript的闭包到底是什么,有什么用,今天在网上看到了一篇讲JavaScript闭包的文章(原文链接),讲得非常好,这下算是彻底明白了JavaScript的闭包...

    javascript闭包(Closure)用法实例简析

    本文实例讲述了javascript闭包(Closure)用法。分享给大家供大家参考,具体如下: closure被翻译成“闭包”,感觉这东西被包装的太学术化。下面参考书本和网上资源简单探讨一下(理解不当之处务请留意)。 1、什么是...

    JavaScript中的闭包原理分析

    我们来看一个定义: Closure 所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式...“类是带行为的数据,而闭包是带数据的行为”,在JavaScript中我们用函数的定义代替类的定义,用闭包代替了setter/

    JavaScript 闭包深入理解(closure)

    其实这句话通俗的来说就是:JavaScript中所有的function都是一个闭包。不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的“闭包”。看下面这段代码: function a() { var i = 0; ...

    Javascript的闭包详解

    本文将以例子入手来介绍Javascript闭包的语言特性,并结合一点 ECMAScript语言规范来使读者可以更深入的理解闭包。 注:本文是入门文章,例子素材整理于网络,如果你是高手,欢迎针对文章提出技术性建议和意见。本文...

    揭开Javascript闭包的真实面目

    对于初学者来说,理解Javascript闭包(closure)还是比较困难的,而撰写此文的目的就是用最通俗的文字揭开Javascript闭包的真实面目,让初学者理解起来更加容易一些。

Global site tag (gtag.js) - Google Analytics