JS闭包,闭包的应用中关于立即执行函数的疑惑?

最近在学习闭包时,遇到一个例子,有些想不明白,想请教一下各位大佬。

<button>测试1</button>
<button>测试2</button>
<button>测试3</button>
<script type="text/javascript">
window.onload = function(){ 
    var btns = document.getElementsByTagName('button')
    for (var i = 0; i < btns.length; i++) {
          (function (i) {
            btns[i].onclick = function () {
              console.log('第' + (i + 1) + '个')
            }
          })(i)
        }
}

</script> 

对于这个代码,使用闭包能实现打印点击第几个我有一些小疑问。先来说说我的理解吧。
for循环的时候会创建三个自执行函数,本来自执行完毕之后,就会被JS的回收机制给回收。但是里面的btns[i].onclick = function(),由于父函数内的子函数被外部变量引用了,所以就形成了闭包。当点击按钮时,内部的function因为没有变量i,就会向上去找,又因为形成了闭包,传入的i没有被销毁,一直保存在内存中,所以就能成功打印出对应的值。
不知道我的这个理解对不对,还希望大佬能够指点。

阅读 1.6k
2 个回答

前面的元素查询以及循环和闭包无关,先搁置不管。为了方便理解,姑且给 function 编个名字:

 (function A(i) {
    btns[i].onclick = function B() {
      console.log('第' + (i + 1) + '个')
    }
 })(i)

这里复习一下闭包的定义:

当函数 A 的内部函数 B 被 A 以外的一个变量引用的时候,就创建了一个闭包。

这里的每个 btns[i] 毫无疑问都是 A 外部的一个 DOM 对象,所以,这里即是创建了闭包。
因为每个按钮对象都包含了函数 B 的引用,所以当 A 执行结束后,它的作用域对象并没有被垃圾回收,而是继续在内存中保留。
当按钮被点击时,执行绑定的函数 B,因为 B 的作用域中不包含变量 i,所以会去它的父级作用域
也就是函数 A 的作用域中寻找,因为闭包的原因,A 的作用域对象依旧存在,所以可以顺利的拿到 i 的值。

把里面的i换个名字好理解一点

;(function (index) {
    btns[index].onclick = function () {
      console.log('第' + (index + 1) + '个')
    };
})(i)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题