闭包

63 阅读1分钟

什么是闭包:

在封闭的作用域中,添加私有数据 想重用变量又想保护这个变量不被篡改的一种机制,是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量.

 <body>
    <input type="text" placeholder="请输入要查询的学生姓名" id="ip" />
    <button id="btnSet">设置成绩</button>
    <button id="btnGet">查询成绩</button>
    <p id="pInfo">成绩显示区</p>

    <!-- 
    存储5个学生的成绩【数学,编程,打游戏】在各自的闭包中
    根据姓名查询不同学生的成绩
    -->
    <script>
      function scrore(name) {

        /* 闭包内的私有数据 */
        const scores = {
          chinese: 0,
          math: 0,
          coding: 0,
        };

        /* 
        返回闭包内数据的操作API对象
        只要有人访问/引用这个对象
        =>score函数无法释放
        =>形成闭包
        =>每个闭包都可以独立地存储各自的学习成绩  
        */
        return {
          // 设置学习成绩
          set(key, value) {
            scores[key] = value;
          },

          // 查询所有
          getAll() {
            return `${name}:${JSON.stringify(scores)}`;
          },
        };
      }
    </script>

    <!-- 业务逻辑 -->
    <script>
        const arr = ["张三疯","尼古拉斯赵四","隔壁老王"]

        /* 
        {
            name1:成绩闭包操作api,
            name2:成绩闭包操作api
        }
        */
        const obj = {}

        /* 一人一个成绩闭包的操作API */
        const scores = arr.forEach(
            // {张三疯:张三疯的成绩操作API}
            name => obj[name]=scrore(name)
        )
       
        // console.log(obj);
        /* 设置成绩 */
        btnSet.onclick = function(){
            // 拿到用户的输入 张三疯:chinese:50
            let [name,key,value] = ip.value.split(":")

            // 调用name对应的闭包中的set设置该生的科目成绩
            obj[name].set(key,value)
            
        }

        /* 根据姓名查询学生的全部成绩 */
        btnGet.onclick = function(){
            const name = ip.value
            // 根据名字拿到其成绩闭包的操作API 进而调用getAll
            pInfo.innerText = obj[name].getAll()
        }
    </script>
  </body>

闭包有三个特性:

  1. 函数嵌套函数
  2. 函数内部可以引用外部的参数和变量
  3. 参数和变量不会被垃圾回收机制回收

闭包的优点是:

  1. 变量被保存起来没有被销毁,随时可以被调用
  2. 只有函数内部的子函数才能读取局部变量,可以避免全局污染

缺点是:

  • 如果闭包使用不当,就会导致变量不会被垃圾回收机制回收,造成内存泄露

银行存钱和取钱,查询余额