javascript-闭包是什么

来源:互联网 发布:广东省软件企业认定 编辑:程序博客网 时间:2024/04/29 18:44

闭包

在讲闭包前先要知道javascript定义函数的方式有两种:
一种是函数声明,其语法是这样的

function functionName(){    //函数体}

第二种创建函数的方式是使用函数表达式。函数表达式有几种,下面是最常见的一种

var functionName=function (){    //函数体}

这种形式看起来好像是常规的变量赋值语句,即创建一个函数并将它赋值给变量functionName。这种情况下创建的函数叫做匿名函数。解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明,并使其在执行任何代码前可用,至于函数表式,则必须等到解析器执行到它所在的代码行。才会真的被解释执行

闭包这个概念一直有听说过,但也不是很清楚,所以自己花了点时间去弄明白,我们也常常把匿名函数和闭包搞混。闭包是指有权访问另一个函数作用域中的变量的函数,注意,闭包是一个函数,创建闭包的常见方式,就是在一个函数内部创建另一个函数,下面举一个例子。

function creatComparisonFunction(prop){        return function (object1,object2){            var value1=object1[prop];//这里访问了外部函数中的变量prop            var value2=object2[prop];            if(value1<value2){                return -1;            }else if(value1>value2){                return 1;            }else{                return 0;            }        };    }

即使这个内部函数被返回了,而且还是在其他地方被调用了,但它仍然可以访问变量prop,之所以还能访问这个变量,是因为内部函数的作用域链中包含creatComparisonFunction( ) 的作用域。
当某个函数被调用时,会创建一个执行环境及相应的作用域链。然后,使用arguments和其他命名参数的值来初始化函数的活动对象。但在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数处于第三位。。。。。,直到作为作用域链终点的全局执行环境。而闭包的情况有所不同,在另一个函数内部定义的函数会将包含函数(即内部函数)的活动对象添加到它的作用域链中。因此,在creatComparisonFunction( )
函数内部定义的匿名函数的作用域中,实际上将会包含外部函数creatComparisonFunction( ) 的活动对象。但这
种作用域配置机制引出一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值

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

这个函数
会返回一个数组,位置0的函数返回0,位置1的函数返回1,以此类推。但实际上,每个函数都返回10。因为每个函数的作用域链中都保存着creatFunction()函数的活动对象,所以他们都引用同一个变量i。当creatFunction()函数返回后,变量i的值是10。result[i]
后面的匿名函数没有立即执行,所以result[i]表示一个函数,result[i]()则是将这个匿名函数执行,匿名函数里的变量i的取值则为其外部函数中变量i的取值一样,还记得上面说的。闭包只能取得包含函数中任何变量的最后一个值,所以此匿名函数的i全都是10。

以上说明,例子参考javascript高级程序设计第三版

个人认为引起闭包这种特性的根本原因是函数表达式不会被立即执
,在外部函数执行完后仍然是函数体没有被解析