JS之 闭包 面试经典(Es6++)

概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域

简单理解:闭包(closure) = 内层函数 + 外层函数的变量

在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

一般就是一个函数A,return其内部的函数B ,被return出去的B 函数能够在外部访问A函数内部的变量,这时候就形成了一个B函数的变量背包。

闭包的最典型的应用是实现回调函数(callback) 

入门简单写法:(实例)

 <script>
        // 里层函数f()加外层函数outer()的变量 捆绑在一起形成闭包
      function outer() {
        const a = 2
        function f() {
            console.log(a)
        }
        f()
      }
      outer()
    </script>

常见的闭包的形式,外部可以访问使用 函数内部的变量,写法:

 <script>
      function outer() {
        const a = 2
        function inner() {
            console.log(a)
        }
        return inner  //返回函数
      }
    //   outer() === inner  === function inner() {}
    // const fn = function inner() {}
       const fn = outer()
       fn()  //调用函数  外层函数使用内部函数的变量
    </script>

 闭包的应用 : 实现数据私有

实例:做一个统计函数调用次数,函数调用一次,就++

 // count 为全局变量,能轻易被修改
    let count = 1
    function fn() {
      count++
      console.log(`函数被调用${count}次`)
    }
    fn()  //2
    fn()  //3
 //实现数据私有,无法直接修改count
  function fn() {
      //在外层申明一个函数 使i变成局部变量 
      let count = 1
      function fun() {
        count++
        console.log(`函数被调用了${i}次`)
      }
      return fun
    }
    const result = fn()
    result() //2
    result() //3

闭包的作用:

1、封闭数据实现数据私有,外部也可以访问函数内部的变量

2、闭包很有用,它允许将函数与其所操作的某些数据(环境)关联起来

3、使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收

注意:

内存泄漏:函数一直被使用,变量不会被回收(没有销毁)

内存浪费:不仅仅因为它常驻内存,更重要的是,对闭包的使用不当会造成无效内存的产生。

案例:循环中使用闭包解决var定义函数的问题

for (var i = 1; i <= 5; i++) {
          // 定时器 延迟函数
            setTimeout(function timer() {
                console.log(i)
            }, i * 1000)
        }

首先,setTimeout 是一个异步函数,所以会先把循环全部执行完毕,这时候i 就是6,所以会输出一堆6。

解决方法:

第一种:使用闭包的方法

  for (var i = 1; i <= 5; i++) {
            ; (function (j) {
                setTimeout(function timer() {
                    console.log(j)
                }, j * 1000)
            })(i)
        }

 上述代码中,首先使用了立即执行函数将i 传入函数内部,这时值就被固定在参数j 上面不会改变,当下次执行timer 这个闭包时,就可以使用外部函数的变量j ,从而达到目的。

第二种:使用setTimeout 的第三个参数,这个参数会被当成timer 函数的参数传入

 for (var i = 1; i <= 5; i++) {
            setTimeout(
                function timer(j) {
                    console.log(j)
                },
                i * 1000,
                i
            )
        }

 第三种:使用let 定义i 来解决问题,这个也是最为推荐的方式

  for (let i = 1; i <= 5; i++) {
            setTimeout(function timer() {
                    console.log(i)
                }, i * 1000)
        }

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linsir 一啵叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值