闭包

时间:2022-11-17 10:12:44

一、作用域

  • JavaScript作用域:分为全局作用域、局部作用域。变量在某个范围内起作用和效果,目的是为了提高程序的可靠性和减少命名冲突。

  • 变量的作用域:根据作用域的不同我们变量分为全局变量和局部变量。两种变量其主要区别是函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。

  • 作用域链:

    • 根据内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称为作用域链

    • 只要是代码,就至少有一个作用域。

    • 写在函数内部的局部作用域。

    • 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。

1.全局变量
  • 概念:在全局作用域下的变量,在全局下都可以使用。
  • 如果在函数内部没有声明直接赋值的变量也属于全局变量。
  • 只有浏览器关闭的时,全局变量才会销毁,比较占内存资源。
    • 全局作用域:整个script标签中,或者是一个单独的js文件。
2.局部变量
  • 在局部作用域下变量,即在函数内部的变量就是局部变量,只能在函数内部使用。
  • 函数的形参也可以看做是局部变量。
  • 当我们程序执行完毕时,局部变量就会销毁,比较节约内存资源。
    • 局部作用域(函数作用域):在函数内部就是局部作用域,这个代码的名字(变量)只在函数内部起作用和效果。

二、理解闭包

1.闭包的概念
  • 闭包是指有权访问另外一个函数作用域中的局部变量的函数。声明在一个函数中的函数,叫做闭包函数。而且内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
2.闭包的特点
  • 让外部访问函数内部变量成为可能。
  • 局部变量会常驻在内存中。
  • 可以避免使用全局变量,防止全局变量污染。
  • 会造成内存泄漏(有一块内存空间被长期占用,而不被释放)。
3.闭包的分析
  • 闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,并且互不干扰。
  • 闭包会发生内存泄漏,每次外部函数执行的时候,外部函数的引用地址不同,都会重新创建一个新的地址。
  • 但当外部函数运行结束甚至销毁时,局部的变量key=value,尽管key被垃圾回收机制给回收了,但是value仍不会被回收,会变成一个*变量留下引用的指针。
4.闭包的实现案例
  • 利用闭包的方式,输出点击项的索引值

    <ul class="closure">
        <li>苹果</li>
        <li>香蕉</li>
        <li>橘子</li>
        <li>西瓜</li>
    </ul>
    <script>
    	// 获取所有的li元素
    	let lis = document.querySelectorAll('.closure li')
        // 利用for循环创建了4个立即执行函数
        for (let i = 0; i < lis.length; i++) {
            (function (i) {
                lis[i].addEventListener('click', function () {
                    console.log(i)
                })
            })(i)
        }
    </script>
    
  • 利用闭包的方式,3秒钟之后,打印所有li元素的内容

    <ul class="closure">
        <li>苹果</li>
        <li>香蕉</li>
        <li>橘子</li>
        <li>西瓜</li>
    </ul>
    <script>
    	// 获取所有的li元素
    	let lis = document.querySelectorAll('.closure li')
        for (let i = 0; i < lis.length; i++) {
            (function (i) {
                setTimeout(() => {
                    console.log(lis[i].innerHTML)
                }, 3000)
            })(i)
        }
    </script>