javascript 学习笔记(3) 闭包

来源:互联网 发布:增大音量的软件 编辑:程序博客网 时间:2024/05/16 07:42

闭包是什么?有的朋友会说,闭包就是匿名函数,其实这样的说法是不对的。《javascript高级程序设计》一书中关于闭包我觉得

是说的最好的,就是闭包是指有权访问另外一个函数作用域中的变量的函数。


要理解闭包,首先我们要清楚什么是作用域链。当某个函数被调用时,会创建关于这个函数的作用域链。在作用域链的头部,是

该函数的arguments和其他命名的参数组成的活动对象。而处于第二位的,是距离该函数最近的外部函数的活动对象,然后依次

类推,直到到达全局的活动对象。书上有图,我这里就不画了。


而在创建一个函数的时候,会提前创建一个预先包含外部函数的活动对象的作用域链,并存储在[[scope]]内部属性中,当函数被调用时,

就创建该函数的活动对象并将它加在[[scope]]链条的顶端,从而完成作用域链的创建。当函数执行的时候,查找变量的过程就在作用域

链上进行,从头到尾查找同名的变量,直到找到为止。

从本质上讲,作用域链本质上是一个指向变量对象的指针列表,它仅仅是引用了活动对象(这里很关键,是引用而非保存副本)。


这里列出一个例子:

function createFunction(){   var result = new Array();   for( var i=0;i<5;i++){      result[i] = function(){        return i;      }   }}


这里我们通过一个createFunction函数创建了一个5个function的数组,数组中每个函数都是一个闭包,每个闭包的作用域链中都引用了createFunction

的活动对象,具体来说,该活动对象有两个成员,一个result数组一个i变量。大家不了解闭包的时候乍一看也许觉得这五个函数分别返回0,1,2,3,4;

其实这五个函数返回的值都是5。这是为什么呢?原因就在这五个函数的作用域链是引用的createFunction,在createFunction执行完毕之后,i值变为

了5,所以这五个函数的返回值也都是5了。那大家要问,我们怎么做才能做到我们想要的效果呢?只需要将代码编程如下:

function createFunction(){   var result = new Array();   for( var i=0;i<5;i++){      result[i] = function(num){        return function(){           return num;        }      }(i);   }}

在这段代码中,我们result数组中的闭包函数的作用域链实际上有三个节点(不包含全局活动对象),分别是自己的空的活动对象,外层匿名函数的活

动对象(包含num),以及createFunction的活动对象。而每个外层匿名函数的活动对象中num值是不一样的,这个是因为我们执行了外层匿名函数从而

在构造作用域链的时候引用了完全不同的num值。(这里可能比较抽象,但是大家想想应该没问题)。


有关闭包的内存泄露这里就不多讲了,大致就是在函数中使用了引用dom对象后需要将对象赋为null以切断作用域链中的循环引用。


闭包的一个高级用处是模仿块级作用域。由于js本身是没有块级作用域的,即下面代码可以执行成功:

function outputNumbers(counts){    for(var i =0;i<counts;i++){      alert(i);    }    alert(i)//counts;}

块级作用域的标准写法如下:

(function(){})()


在function中添加var变量,就能做到只有function中的代码可以访问,出了function则无法访问,即实现了块级作用域。例子如下;

var global_obj = null;(function(){   var private_name = "roger";   global_obj = {     setName:function(name){       private_name = name;     },     getName:function(){       return private_name;     }   };})();

以上就是我看《javascript高级程序设计》的读后感,后面的内容有机会再看吧,目前就这些了,希望各位看官可以一起交流!




0 0
原创粉丝点击