乱谈闭包

关于闭包,有各类各样的解释,百科给出的解释是:数组

在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即便已经离开了创造它的环境也不例外。因此,有另外一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时能够有多个实例,不一样的引用环境和相同的函数组合能够产生不一样的实例。闭包

个人理解是:函数执行造成私有的做用域。 那么他就有两个做用:保护和保存。app

闭包的保护做用

闭包造成的私有做用域能够保护里面的私有变量不受外界干扰。例如咱们常常使用的:函数

var a = 5;
(function () {
    var a = 10;
    console.log(a)   // ---->10
})()
console.log(a)   // ---->5
复制代码

这时在全局中有个a变量,私有做用域中也有个a变量,使用闭包,咱们再修改私有做用域中的同名变量是,不会对全局产生影响,避免形成全局污染。post

闭包的保存做用

造成一个不销毁的私有做用域,保护函数执行的上下文。例如以前咱们写函数的防抖和节流的时候:ui

function debounce(fn, time) {
    let Timer;
    return () => {
        Timer && clearTimeout(Timer)
        Timer = setTimeout(() => {
            fn.apply(this, arguments)
        }, time)
    }
}
复制代码

debounce函数保存了一个计时器id的变量Timer,debounce执行 造成一个可让返回函数访问到的私有做用域(函数的上级做用域是它定义时所处的做用域),每次调用返回函数的时候均可以访问获得这个Timer。this

闭包的反作用

举个总是被拿来举的闭包例子:spa

var liList = document.querySelectorAll('li')
for (var i = 0; i < liList.length; i++) {
    (function (i) {
        liList[i].onclick = function () {
            console.log(i)
        }
    })(i)
}
复制代码

因为返回的函数被外部的onclick事件引用了,闭包造成的私有做用域没法被销毁,内存没法被回收,回收机制参考js垃圾回收机制,容易形成内存泄漏。code

若要手动释放内存,则那么写:事件

for (var i = 0; i < liList.length; i++) {
    liList[i].onclick = null
}
复制代码

并非全部闭包都会形成内存没法回收,例如:

function fn(i) {
    return function (n){
        console.log(i + n)
    }
}

fn(2)(3)
复制代码

fn造成的私有做用于中,变量并无被外界所引用,函数执行完成后,内存马上进行回收。

相关文章
相关标签/搜索