今天试了几个例子,尝试理解了一下js闭包的用法,以及垃圾回收机制。尝试的代码放在下边,注释是我对执行结果的理解。
例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function f1(){ var n=1; let nAdd=function(){n+=1}; let log = function(){console.log(n)};
function f2(){ console.log(n); } return f2; }
f1(); nAdd(); log(); f1()(); nAdd(); log()
|
例2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function f1(){ var n=1; nAdd = function(){n+=1} log = function(){console.log(n)}
function f2(){ console.log(n); }
return f2; }
var a = f1(); nAdd(); log(); var b = f1(); log(); a(); b();
|
例3:
问题描述:
实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即result[i](),结果与 fn(arr[i]) 相同。
看到这个问题,我写出了如下代码:
1 2 3 4 5 6 7 8 9 10 11
| result = []; for(var i = 0; i < arr.length; ++i){ result.push(function(){ return (function(n){ return fn(arr[n]) })(i) }) }
return result
|
显然,这个结果是错的。result内部push的函数中,仍然使用了外部发生变化的量i,因此最后的值是NAN(循环结束后i指向arr.length,因此arr[i]其实不存在。
正确做法如下:
1 2 3 4 5 6 7 8 9 10 11
| result = []; for(var i =0; i < arr.length; ++i){ result.push(function(n){ return function(){ return fn(arr[n]) } }(i)) }
return result;
|
此时result返回的函数内部没有用到任何发生变化的量(i),因此也就可以返回正确的结果。
返回闭包时,一定要想清楚闭包内的变量指向,不要在闭包内引用任何外部的会发生变化的量。慎用闭包,小心内存泄露。