最近在学习闭包时,遇到一个例子,有些想不明白,想请教一下各位大佬。
<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没有被销毁,一直保存在内存中,所以就能成功打印出对应的值。
不知道我的这个理解对不对,还希望大佬能够指点。
前面的元素查询以及循环和闭包无关,先搁置不管。为了方便理解,姑且给 function 编个名字:
这里复习一下闭包的定义:
这里的每个
btns[i]
毫无疑问都是 A 外部的一个 DOM 对象,所以,这里即是创建了闭包。因为每个按钮对象都包含了函数 B 的引用,所以当 A 执行结束后,它的作用域对象并没有被垃圾回收,而是继续在内存中保留。
当按钮被点击时,执行绑定的函数 B,因为 B 的作用域中不包含变量
i
,所以会去它的父级作用域也就是函数 A 的作用域中寻找,因为闭包的原因,A 的作用域对象依旧存在,所以可以顺利的拿到 i 的值。