闭包的概念
各种专业文献上的"闭包"(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。函数和函数内部能访问到的变量也叫环境的总和,组成一个闭包。
闭包的作用
-
可以读取函数内部的变量。
-
一个就是让这些变量的值始终保持在内存中。
function foo() { var a = 2; return function fun1() { console.log(a) } } var fun2 = foo() fun2() //2在上面的例子中,fun1 能够访问 foo 的内部作用域。在 foo()执行后,把 foo()的返回值 fun1 赋值给 fun2 并调用 fun2。打印出了结果 2 。
此时,我们可以说 fun1 记住并访问了所在的词法作用域 或者说 fun2 访问了另一个函数作用域中的变量。
由于引擎有自动的垃圾回收机制,在 foo()执行后(不再使用),通常 foo 的整个内部作用域会被销毁,对内存进行回收。闭包的神奇之处正是可以阻止这件事情的发生,因为 fun1 依然持有对该作用域的引用,这个引用就叫做闭包。
-
闭包可以用来隐藏一个变量,比如有一个变量,我们不想别人直接访问它,而是间接使用你提供的方法来操作它,就可以使用闭包。
function outerFn(){ var i = 10; window.add = function(){ i+=1; } return i } var inner = outerFn(); inner(); //10 add(); inner(); //11
使用闭包的注意点
-
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在 IE 中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
-
闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
let add = null function f1(){ var n=999; add=function(){ n+=1; } function f2(){ return n; } return f2; } var result=f1(); result(); // 999 Add(); result(); // 1000此时 add 方法是一个公有方法,可以直接操作,改变 n 的值,应当注意这一点。