闭包

94 阅读2分钟

1、作用域和作用域链

  • 作用域 变量和函数的可使用范围叫做作用域。作用域可以认为它是一个封闭的空间,只允许在这个封闭的空间内进行一些操作,也将这个封闭空间称为私有作用域。

  • 作用域链 每个函数都会有一个作用域,查找变量或函数时,由局部作用域到全局作用域依次查找,这些作用域的集合就称为作用域链。

  • 函数作用域 函数执行时,就会在内存中创建一个私有作用域——封闭的空间。正常情况下,函数执行完成后,这个私有作用域(封闭的空间)就会销毁,但闭包不会被销毁。

  • 内存回收机制 系统自动会清理回收不到的内存。

  • 内存泄露 不再用到的内存,没有及时释放,就叫做内存泄漏。

  • 导致内存泄露原因: 内存泄漏是指我们已经无法再通过js代码来引用到某个对象,但垃圾回收器却认为这个对象还在被引 用,因此在回收的时候不会释放它,导致了分配的这块内存永远也无法被释放出来。如果这样的情况越 来越多,会导致内存不够用而系统崩溃。

2、闭包

2.1、闭包的含义

函数执行,形成一个私有的执行上下文,保护里边的私有变量不受外界的干扰,除了保护私有变量外, 还可以保存一些内容,这样的模式叫做闭包。

总之,在一个函数A内定义一个函数B,这个函数B一直保持有对外部函数A中作用域的访问权限,即B函数一直拥有访问A函数内变量的权限。

2.2、闭包的作用

1、保护:用来保护一些私有变量不被污染; 将私有变量放在一个私有的作用域中,防止相互之间的变量命名冲突;

2、保存:用来保存私有的变量;如循环绑定事件引发的索引问题

2.3、闭包的应用

循环绑定事件索引问题

var btnBox = document.getElementById('btnBox'),
  inputs = btnBox.getElementsByTagName('input')
  var len = inputs.length;
  for(var i = 0; i < 1en; i++){
    inputs[i].onclick = function () {
        alert(i) //循环输出len的值
    }
}
  • 1、使用闭包解决
var btnBox = document.getElementById('btnBox'),
        inputs = btnBox.getElementsByTagName('input')
        var len = inputs.length;
        for(var i = 0;i<len;i++){
            (function(i){
                inputs[i].onclick = function () {
                    alert(i)
                 }
            })(i)
}
  • 2、使用自定义属性
var btnBox = document.getElementById('btnBox'),
        inputs = btnBox.getElementsByTagName('input')
        var len = inputs.length;
        for(var i = 0;i<len;i++){
            inputs[i].index=i
            inputs[i].onclick = function () {
                alert(this.index)
            }
}
  • 3、ES6
var btnBox = document.getElementById('btnBox'),
        inputs = btnBox.getElementsByTagName('input')
        var len = inputs.length;
        for(let i = 0;i<len;i++){
            inputs[i].onclick = function () {
                alert(i)
            }
}

2.4、闭包的优缺点

  • 优点:通过创建私有作用域(闭包),用来保存私有变量;
  • 缺点:生成多个不销毁的私有作用域(堆内存),影响性能;

参考:juejin.cn/post/684490…