【JS基础】闭包
概念:闭包是指有权访问另一个函数作用域中的变量的函数。在JS中,只有函数内部的子函数才能读取局部变量,所以闭包可以简单理解成‘定义在一个函数内部的函数’。
例题
1 function test() { 2 var n = 4399; 3 function add(){ 4 n++; 5 console.log(n); 6 } 7 return {n:n,add:add} 8 } 9 var result = test(); 10 var result2 = test(); 11 result.add(); // 4400 12 result.add(); // 4401 13 console.log(result.n); // 4399
function test() { var n = { num: 4399 }; function add(){ n.num++; console.log(n); } return {n:n,add:add} } var result = test(); var result2 = test(); result.add(); // {num: 4400} result.add(); // {num: 4401} console.log(result.n); // {num: 4401}
tips:上面例题会涉及深浅拷贝的问题
接下来看看用let声明和var声明的输出会有什么不同
function fn() { let arr = [] for (let i = 0; i < 5; i++) { arr[i] = function() { return i } } return arr } let list = fn() list[0]() // 输出 0
function fn() { let arr = [] for (var i = 0; i < 5; i++) { arr[i] = function() { return i } } return arr } let list = fn() list[0]() // 输出 5
下面是匿名函数,听说有人会混淆,所以也放这里供参考
var foo = {n:1}; (function(foo){ console.log(foo.n); // 1 foo.n = 3; var foo = {n:2}; console.log(foo.n); // 2 })(foo); console.log(foo.n); // 3
之前看到一个博主写的例子,这里展示给大家看看
var num = new Array(); for(var i=0; i<4; i++){ num[i] = f1(i); } function f1(n){ function f2(){ console.log(n); } return f2; } num[2](); // 2 num[1](); // 1 num[0](); // 0 num[3](); // 3
有评论说不解为什么答案是这样,这里我说说自己的看法:
f1使用了i做参数,把值拷贝给了n,而不是直接使用i变量,因此每个num[i]中的n都是不一样的,如果函数改成下面这样:
var num = new Array(); for(var i=0; i<4; i++){ function f1(){ function f2(){ console.log(i); } return f2; } num[i] = f1(); } num[2](); // 4 num[1](); // 4 num[0](); // 4 num[3](); // 4
这里f1直接使用变量i,导致i没有被回收,所以每个num[i]中的i都是一样的。
总结:
闭包使得Javascript的垃圾回收机制不会收回fn所占用的资源,因为a的内部函数b的执行需要依赖fn中的变量。
看完文章,如果你还是不会解闭包的题目,那一定是我水平有限,说得不够明白,可以留言,我们一起探讨。