闭包

一、产生闭包的条件

  1. 函数内返回函数
function a() {
  var c = 100;
  function b() {
    c = 200;
  }
  return  b;
}
  1. 函数作为参数传入函数中
function b(fn) {
  var c = 100;
  fn(c);
}

注:正常情况变量在使用完后,会被垃圾回收机制进行释放,内部函数使用外部函数的变量,会延长该变量的生命周期,由于不知未来会不会再使用该变量,所以不会触发垃圾回收机制(不是内存泄漏)。

二、使用闭包的场景

  • 为多个dom元素添加点击事件
<!DOCTYPE html>
<html>
  <head>
    <title>为多个dom元素添加点击事件</title>
  </head>
  <body>
    <button>点击</button>
    <button>点击</button>
    <button>点击</button>
    <button>点击</button>
    <button>点击</button>
    <script>
      var btns = document.getElementsByTagName('p');
      // 无论点击哪个按钮,打印出来的都是5
      // 原因:变量i为全局变量,点击事件为异步操作,当初发点击回调时,for循环已经执行完成,此时i=5
      for(var i = 0; i < 5; i++) {
        btns[i].click = () => {
          console.log(i);
        }
      }
      // 依次点击按钮,打印0, 1, 2, 3, 4
      // es5中有全局作用域和函数作用域,立即执行函数形成函数作用域,点击回调函数打印的是当时传入立即执行函数的i值,并不是全局变量i
      for(var i = 0; i < 5; i++) {
        (function () {
          btns[i].click = () => {
            console.log(i);
          }
        })(i)
      }
      // 依次点击按钮,打印0, 1, 2, 3, 4
      // 原因:es6新增了块级作用域,for循环中通过let定义i,每次循环都会在()和{}中形成块级作用域,其中()为父作用域,{}为子作用域,所以子作用域的i为其父作用域中的i
      for(let i = 0; i < 5; i++) {
        btns[i].click = () => {
          console.log(i);
        }
      }
    </script>
  </body>
</html>
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。