和你好好说说js中的函数闭包
之前对函数闭包只有大概的概念,也有在网上搜,可是网上给的都是给了一个例子,大多都还是一个for循环,输出的结果怎么怎么和预期不一样,觉得解释的都不透彻。今天就来好好聊聊函数闭包
在说函数闭包前,要知道作用域链,如果不知道,可以先google,之后会将自己整理的笔记也发上来
最常见创建闭包的方式,是在一个函数中在定义一个函数

如果觉得不好理解,大家可以想象,其实在return那行代码之前是可以再有其他的代码,就像定义了propretyName一样,故说,匿名函数的作用域链包含了createComparisonFuction的作用域链。
一般来讲,当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域。但是,闭包函数的情况又有所不同。
当匿名函数从createComparisonFunction()中返回后,它的作用域链被初始化为包含createComparisonFunction()函数的活动对象和全局变量对象。因此,匿名函数就可以访问在createComparisonFunction()中定义的所有变量,createComparisonFunction()函数执行完毕后,其活动对象也不会被销毁,因为匿名函数的作用域链仍然在这个活动对象。。。。换句话说,当createComparisonFunction()函数返回后,其执行环境的作用域链会被销毁,但它的活动对象仍然会存在内存中,直到匿名函数被销毁。
由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过度使用闭包可能导致内存占用过多,,慎用
知道闭包可以携带包含它的函数的作用域后,我们可以来揭秘for循环,i的值的秘密了
1 function createFunctions(){ 2 var result = new Array(); 3 for(var i=0;i<10;i++) 4 { 5 result[i] = function(){ 6 return i; 7 }; 8 } 9 return result; 10 } 11 12 var funcs = createFunctions(); 13 //每个函数都输出10 14 for(var j=0;j<funcs.length;i++){ 15 document.write(funcs[j]()+"<br/>"); 16 }
上面代码的意思是createFunctions()返回的是一个函数数组,用funcs保存这个数组,对其进行循环,调用对应的函数(即return i),按预计的应该结果是0,1,2,...,9可是运行的结果全是10,10,... ,10.为什么呢?其实只要知道result[i](function(){return i})中的函数是闭包,想必你自己就可以解释原因了。每个函数的作用域链中都保存着createFunctions()函数的活动对象,所以它们引用的都是同一个变量i。在createFunctions()函数返回后,变量i的值是10.
如果,想返回的结果是预期的结果,只需稍作修改即可
1 function createFunctions(){ 2 var result = new Array(); 3 for(var i=0;i<10;i++) 4 { 5 result[i] = function(num){ 6 return function(){ 7 return num; 8 }; 9 }(i); 10 } 11 return result; 12 } 13 14 var funcs = createFunctions(); 15 16 for(var i=0;i<funcs.length;i++){ 17 document.write(funcs[i]()+"<br/>"); 18 }
没有将闭包直接赋值给数组,而是定义了一个匿名函数,并将立即执行该函数的结果赋值给数组。在调用每个匿名函数是我们传入了变量i(记着哟,函数参数是按值传递的,i的值会复制给参数num)。匿名函数的正体,返回一个函数,即之前代码赋值给result的值。
这是看书的读书笔记,来自《JavaScript高级程序设计》,喜欢我的整理的话,给个赞把

浙公网安备 33010602011771号