浅析Javascript闭包的特性

Javascript闭包的定义非常晦涩——闭包,是指语法域位于某个特定的区域,具有持续参照(读写)位于该区域内自身范围之外的执行域上的非持久型变量值能力的段落。这些外部执行域的非持久型变量神奇地保留它们在闭包最初定义(或创建)时的值(深连结)。
简单来说,Javascript闭包就是在另一个作用域中保存了一份它从上一级函数或作用域取得的变量(键值对),而这些键值对是不会随上一级函数的执行完成而销毁。周爱民说得更清楚,闭包就是“属性表”,闭包就是一个数据块,闭包就是一个存放着“Name=Value”的对照表。就这么简单。但是,必须强调,闭包是运行期概念,一个函数实例。
Javascript闭包的实现,通常是在函数内部再定义函数,让该内部函数使用上一级函数的变量或全局变量。
ECMAScript认为使用全局变量是一个简单的Javascript闭包实例。

1.  **var** sMessage = "Hello World";   
2.  **function** sayHelloWorld(){   
3.  alert(sMessage);   
4.  };   
5.  sayHelloWorld(); 

但它完成没有体现Javascript闭包的特性……
现在比较让人认同的Javascript闭包实现有如下三种

1.  **with**(obj){   
2.  //这里是对象闭包   
3.  }(**function**(){      
4.  //函数闭包   
5.  })()**try**{   
6.  //...   
7.  } **catch**(e) {   
8.  //catch闭包 但IE里不行   
9.  } 

附上我们常常遇到的问题:
要求:
让这三个节点的Onclick事件都能正确的弹出相应的参数。

1.  <ul>
2. <li id="a1">aa</li>   
3.  <li id="a2">aa</li>   
4.  <li id="a3">aa</li>   
5.  </ul>   
6.  <script** type="text/javascript">   
7.  <ul>   
8.  <li id="a1">aa</li>  
9.  <li id="a2">aa</li>   
10. <li id="a3"*>aa</li>  
11.</ul>   
12. <script** type="text/javascript"**>**   
13. for(var i=1; i **< 4**; i++){   
14. var id = document.getElementById("a" + i);   
15. id.onclick = function(){   
16. alert(i);//现在都是返回4      
17. }   
18. }   
19. </script> 

解答:

  1. for(var i=1; i < 4; i++){
  2. var id = document.getElementById("a" + i);
  3. /*
  4. 这里生成了一个匿名函数并赋值给对象 id_i;
  5. */
  6. id.onclick = function(){
  7. /*
  8. 这个i来源于局部变量,无法以window.i或者obj.i的形式在后期引用,
  9. 只好以指针或者变量地址方式保存在这个匿名函数中,
  10. 这就是传说的闭包,所以所有这个过程中生成的事件句柄都使用引用
  11. 的方式来持久这个变量,也就是这些匿名函数共用一个变量i;
  12. */
  13. alert(i);
  14. };
  15. };
    局部变全局
  16. for(var i=1; i < 4; i++){
  17. var id = document.getElementById("a" + i);
  18. id.i=i;//这个i有了根
  19. id.onclick=function(){
  20. alert(this.i)
  21. };
  22. };1.for(var i=1; i < 4; i++){
  23. var id = document.getElementById("a" + i);
  24. window[id.id]=i;//这个i有了根
  25. id.onclick=function(){
  26. alert(window[this.id]);
  27. };
  28. }
    产生一对一的更多Javascript闭包
  29. for(var i=1; i < 4; i++){
  30. var id = document.getElementById("a" + i);
  31. id.onclick = new function(){
  32. var i2=i;//这个i是闭包的闭包
  33. return function(){
  34. alert(i2);
  35. }
  36. };
  37. }
    javascript深入理解js闭包发布:dxy 字体:[增加 减小] 类型:转载

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

一、变量的作用域

要理解闭包,首先必须理解Javascript特殊的变量作用域。

变量的作用域无非就是两种:全局变量和局部变量。

Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。

Js代码

var n=999;

function f1(){
    alert(n);
  }

f1(); // 999

另一方面,在函数外部自然无法读取函数内的局部变量。

Js代码

function f1(){
    var n=999;
  }

alert(n); // error

这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!

Js代码

function f1(){
    n=999;
  }

f1();

alert(n); // 999


二、如何从外部读取局部变量?

出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。

那就是在函数的内部,再定义一个函数。

Js代码

function f1(){

n=999;

function f2(){
      alert(n); // 999
    }

}

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1 就是不可见的。这就是Javascript语言特有的“链式作用域”结构(chain scope),

子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

Js代码

function f1(){

n=999;

function f2(){
      alert(n);
    }

return f2;

}

var result=f1();

result(); // 999


三、闭包的概念

上一节代码中的f2函数,就是闭包。

各种专业文献上的“闭包”(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。

所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

--------------------------------------------------------------------------------------------------------b

四、闭包的用途

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。 一、变量...
    zock阅读 1,074评论 2 6
  • 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。 一、变量...
    zouCode阅读 1,270评论 0 13
  • ● 闭包基础 ● 闭包作用 ● 闭包经典例子 ● 闭包应用 ● 闭包缺点 ● 参考资料 1、闭包基础 作用域和作...
    lzyuan阅读 921评论 0 0
  • 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。 下面就是...
    鲁uin阅读 297评论 0 2
  • 十八怪,原生态, 树折树倒由它摆。 身卧宁静数星辰, 骨化沃土伴林海。 这也怪,那也怪, 少见自然就多怪。 一方水...
    珠江潮平阅读 311评论 20 26