代码一:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>参数</title>
<style>
ul{
list-style:none;
overflow: hidden;
}
li{
float:left;
width:100px;
height:50px;
background-color:red;
margin-right:20px;
}
</style>
</head>
<body>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<script>
var lis=document.getElementsByTagName('li');
for(var i=0;i<lis.length;i++){
(function(i){
lis[i].onclick=function(){
console.log(i);
}
})(i)
}
</script>
</body>
</html>
这段代码中我在for循环内部定义一个自执行的匿名函数吧i传递到匿名函数内部,这样点击不同的li时就可以输出它所在的索引数值,我在想这其中的原理是利用闭包了吗我知道闭包可以保存对父层函数变量的引用,但是我疑惑里面的绑定点击事件的函数到底是闭包吗?闭包不是需要被外界引用才算吗?难道函数嵌套函数但里面的函数没有返回出去呗外界引用也是闭包?以上都是我自己的见解,我想知道这其中的原理是不是利用闭包了?如果不是那是利用什么机制的?如果是闭包那解释下哪个函数是闭包,另外确定下我说的只有被外界引用了才算闭包这句话对不对?
函数并不是说被外界引用了才叫闭包,闭包在函数定义的时候就形成了。
onclick
函数引用的i
并不是for
循环的i
而是匿名立即执行函数里的i
,这个i
由for
循环每次执行传入,这个立即执行函数就被调用了数次,因为每次函数执行上下文都是不同的,这里的i
也就是不同的。这个问题可以说被问了太多次了,SF搜一下都能搜到很多。
简单的说,是闭包。而且在使用立即执行函数把内部的函数包裹起来之前也是闭包。
区别是:
包起来前是1对多的闭包,多个内部函数共享同一个外部的i。所以点击时得到的i都一样。
包起来后是多对多的闭包,多个内部函数共享自己独一无二的i。所以不再出现问题。
这段代码中,foo为闭包,foo是定义中的代码块,x为创建代码块的上下文中数据,闭包就是指代码块使用了创建这段代码块的上下文中数据。
所有的函数都是闭包,因为它们都是在创建的时候就保存了上层上下文的作用域链(除开异常的情况),你的这段代码肯定是使用了闭包,但是也使用了立即执行函数才能达到想要的效果。