九、闭包Closure
-
闭包:在一个函数里边再定义一个函数,创建作用域的连接
-
函数作用域:函数创建时,系统会自带prototype原型属性和scope作用域属性(形成独立作用域 = 封闭的盒子)
-
内存回收机制:系统自动清理不在该作用域下用到的内存空间(js中最好不要写全局变量)
-
可清理前提:某一个变量/对象被引用时,意味着该对象正被使用,系统就不会进行回收
var b = 'abc' //全局变量:js系统不知道何时回收,因此不会被回收 function fn(){ var a = '12' console.log(a) } fn() //当函数执行结束后,a变量将被自动回收(js垃圾回收机制)
-
闭包情况:当内部函数引用外部函数的对象/变量,且外部函数执行完毕,当前作用域也不会回收(不删除的独立作用域)
function fn(){ var a = 'abc' // 不会被垃圾回收机制收回 -- 一直存在内存中 return function(){ console.log(a) } // /出现闭包:里面可以访问外面 } fn()() //a不会被回收,因为系统不确定里面的闭包函数会不会用该变量
-
-
作用域继承:内部函数可访问外部函数的成员,外部不可访问内部(闭包关闭函数的自由变量)
-
-
闭包的特点/作用:
-
一、保护作用域中的私有变量:将局部变量转为全局变量(可读取函数内部变量)
-
二、存储内容:保证该作用域中的变量一直在内存中(不被垃圾回收机制回收)
// 实践:当需要用到DOM事件时(异步),可能需要用到闭包来存储一些数据 var lis = document.getElementsByTagName('li') for (var i = 0; i < lis.length; i++) { (function (i) { lis[i].onclick = function () { alert(i) } lis[i] = null //解决内存滞留问题 })(i) //若不使用闭包,每次打印的i都是4 }
-
-
闭包的弊端/注意点
-
函数中的变量会滞留在内存中:内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题(尤其IE中可能存在内存泄漏)
解决:将闭包函数设置为null
-
当外部函数被当作对象(公用方法),内部函数将该作用域下的变量当作私有属性,一定不要随意改变外部函数变量的值
-