本文共 2755 字,大约阅读时间需要 9 分钟。
前言:
关于闭包的入门篇在,初步引入了闭包的概念,在这篇文章中有一个计数器的案例,如果要兼顾计数变量的安全性和计数功能的实现,使用闭包是一个很好的办法 关于计数器的实现方法,的最后提供了另一种思路:使用函数的对象特性,巴拉巴拉正文
闭包三要素 1.嵌套结构的函数 2.内部函数访问了外部函数的变量 3.在外部函数之外,调用内部函数作用
1.让局部变量变成私有化的长存变量 2.给事件调用的函数传递参数或者内部函数赋值给全局变量,扩大作用域,让内部函数可以在大环境下被调用,运行结果同上
也可以有多个内部函数,操作外部函数的同一个变量
运行结果:
//闭包工厂(函数) function f(){ var x = 1; function e(){ x++; console.log(x); } return e; } var f1 = f();//闭包对象1 var f2 = f();//闭包对象2
运行结果:执行了3次f1后,f1中x的值已经到了4,此时执行一次f2,打印出x的值为2,可以看出,两个闭包对象不干扰
运行结果:不论点击哪一个li,都是输出4
我们可以通过两种办法解决这个问题
方法一:使用闭包工厂创建多个闭包对象function showId(id){ console.log(id); } function clickFunc(id){ function e(){ showId(id); } return e; } function setClick(){ var ary = document.getElementsByTagName('li'); for (var i = 0; i < ary.length; i++){ ary[i].onclick = clickFunc(i + 1); } } setClick();
运行效果:
function showId(id){ console.log(id); } function setClick(){ var ary = document.getElementsByTagName('li'); for (var i = 0; i < ary.length; i++){ (function (){ var id = i; ary[id].onclick = function(){ showId(id + 1); } })(); } }
效果同上:
或者不使用闭包
function setClick(){ var ary = document.getElementsByTagName('li'); for (var i = 0; i < ary.length; i++){ let id = i; ary[id].onclick = function(){ showId(id + 1); } } }
效果同上
调试出的各个li的onclick函数也一样整理一下,应该是,
因为setClick函数里,循环时定义的变量i,在内部函数被直接使用,所以setClick相当于是一个闭包工厂,它的局部变量i是长存的状态,ary[i].onclick在同一个闭包对象中; 当我们点击其中一个li时,showId得到的参数是i+1=3+1=4,而i到达3之后,在闭包中是不再存储累加结果的,所以showId得到的i一直是3; 如果我们将i与id区分开,就能避免i的累加对内部函数参数的影响,即在setClick的内部函数的内部创建了多个闭包对象(记为ID1,ID2,ID3),i依然长存,但不影响闭包对象ID们的参数 循环时,随着i的累加,而创建出闭包对象,i+1已经传到变量id上了所以,在使用for循环给内部函数传参时,如果不想要i的累加影响内部函数,简单的办法就是,使用立即执行,或直接用let定义一个变量,隔开内部函数与外部变量的直接联系
如果有更能说服我的理解,我再来更新
转载地址:http://ziuk.baihongyu.com/