浅析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.  
    2.
  • aa
  • 3.
  • aa
  • 4.
  • aa
  • 5.
6. 7.
    8.
  • aa
  • 9.
  • aa
  • 10.
  • aa
  • 11.
12. ** 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.

解答:

  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

四、闭包的用途

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

你可能感兴趣的:(浅析Javascript闭包的特性)