匿名函数与闭包
匿名函数
所谓匿名函数就是没有名字的函数,即创建一个没有名字的函数对象,可以将这个函数对象赋给一个var,或者作为参数传递,作为函数返回值等等。
var fcn = function() { return 0; };
闭包
所谓闭包就是在函数中定义的函数,这个函数一般用来做返回值(即用一个函数来生产函数)。那么返回的这个内部函数就是闭包了。如:
这里返回的fcn就是闭包。为什么闭包中可以正常使用propertyName呢?它并没用通过参数列表传入fcn中呀!这里的机制是通过作用域链实现的。每个作用域中的活动对象(函数形参,局部变量,arguments等等)保存在作用域节点中,作用域节点串接起来形成作用域链。每当有函数调用,将其作用域节点加到链的前端,调用结束时,从链前端删除(即失去引用,使被垃圾回收)。但是 闭包并不会,因为闭包被返回了,所以虽然它的外部函数createCmpFcn结束了,但是内部函数闭包fcn还存在,因此对外部函数的作用域节点的引用还存在,fcn的作用域链被初始化为createCmpFcn--->window,因此闭包中可以访问已经结束的外部函数的活动对象。function createCmpFcn(propertyName) { return function(obj1,obj2) { var value1 = obj1[propertyName]; var value2 = obj2[propertyName]; if(value1<value2) { return -1; } else if(value1 == value2) { return 0; } else { return 1; } }; } var fcn = createCmpFcn("name");
如图可以看到,每个函数有个SCOPE属性,指向该函数的作用域链,这个作用域链最下端为自身。在函数自身未被调用的情况下,这个链中是没有自身的。它最初被初始化为其定义处的作用域链,然后调用时再根据所处的位置压入一些作用域,最后压入自身的作用域。所以闭包的作用域中总是有其外部函数的。另外,一个外部函数中定义的多个闭包,引用的是同一个外部函数作用域,因此是共享同一套外部函数活动对象的。