javascript闭包详解
秩序
当一个同事去面试时,面试官问了一个问题:你会写一个壁橱,我会看吗所以同事们很快就写了下面的代码:
复制代码代码如下所示:
函数FN(){
警报('Hello Javascript闭包!啊!妈妈蛋,E文本不好,找翻译写出单词闭包。
}
(FN);
然后面试官摇了摇头说:这怎么可以叫做收尾呢最后,两个人在争吵,同事们都坏了,面试官是什么(这个故事纯属虚构,任何相似纯属巧合)
倒闭可能是很多人眼里的一个大而坏的技术,在很多人眼里只能是封闭的关闭:
例1:
复制代码代码如下所示:
函数FN(){
返回函数(){
警报('example 1);
}
}
FN()()();
示例1 ps:这看起来不是很高级,看起来这个人的水平不是很好。
例2:
复制代码代码如下所示:
(函数(){())
警报('example 2);
});
示例2 ps:这看起来比上一个更高级,第一个括号也增加了分号。为什么要加分号好吧,我们把这个问题留在这里,稍后再谈。
例3:
复制代码代码如下所示:
函数FN(){
警报('example 3)
(});
例3 PS:这是最高级的,简单的挂天,我读得少,你不骗我!
楼主读书不多,只能写这三种封闭,认为博客可以写更多优秀的闭合;所以请停止我徒劳的下一步的研究,作用机理,看来有人已经知道了,肯定是范围,我真的不想加入这场冠军,这差异总是感到一点乐趣,这几件事可以一直在一起,你为什么要重复老习惯,先在守则上:
复制代码代码如下所示:
var = 10;
函数FN(){
警报(N);
var = 9;
警报(N);
}
(FN);
简单地说,我们(主线图只附带Windows绘图软件,请。)。如果你有更好的推荐)分析:
分析1
从图中,我们可以看到两个作用域,一个是窗口范围(顶层范围),另一个是在调用FN时形成的私有域,作用范围是什么,作用域实际上是代码执行的环境,一个学习环境是一所学校的学生,相当于他的行动学派。如果这个学生很调皮,晚上他经常去网吧玩游戏,这相当于形成一个私人的环境,那就是网吧。fanqiangok!这就像一个地主TM板栗自己,不由感叹:少壮不努力,它长大了,还是回到主题,事实上,回调函数的定义是指一段代码的描述(红色方块图),这叫FN时(图绿色框)时,就会形成一个范围,当然,在执行前将预解释代码的范围,我不会告诉你这场将于何时执行完毕后销毁,FN称将形成一个新的范围,然后进行预解释和执行的代码,最后完成了破坏。
理解闭包
我们知道当函数被调用时,一个函数被调用来形成一个私有作用域(执行环境),而私有作用域是一个闭包。让我们回顾一下第一次采访的故事,以及我写的三个例子。它们都是闭包。实际上,这三个例子都是常用的闭包形式。
应用场景
现在有这样一个需求:在HTML页面中有一个UL标记,在UL下有5个LI标记,这需要李的任意点击来弹出被点击的李的索引(索引从0开始),并且HTML结构如下所示。
复制代码代码如下所示:
表1
表2
表3
表4
表5
我很快就写出了下面的代码:
复制代码代码如下所示:
VaR LIS = document.getelementbyid('ul)。GetElementsByTagName(李的);
对于(var i = 0,len = lis.length;我< len;i++){
LIS {我}。onclick =函数(){
警报(一);
};
}
最后的测试是看需求是否完美。
人们发现,不管它击中多少次,它最终会产生结果。需求期望的结果是:单击列表1,弹出0,单击列表2,弹出1,单击列表3,播放2……此时此刻,我只想用这张图片描述当前的心情。
(当样机在设计要求不运行时演示)
怎么这么好,为什么它总是弹出5从理论上讲这是非常正确的,我们不妨画一张图来分析一下。
事实上,我们只是给每个李onclick描述字符串保存功能。字符串的内容是红色框中的内容。如果你还不相信的话,我在照片里就知道了。
Chrome控制台下输入:LIS { 4 }。onclick,其值是函数的描述,当我们点击列表中的第五,相当于LIS { 4 }。onclick(),调用函数的描述,我们知道,函数将形成私人范围内执行,在私人域名的作用是先解释,然后执行代码,在这段时间我会去,不在我的私人领域的角色,然后走到窗边域找到我,所以每个点击弹出5。
显然上面的代码不能满足这个要求,我们的代码是不正确的,我们考虑问题的原因。事实上,原因是每次点击在我下面的窗口中读取时,此时i的值已经是5,所以下面的代码:
方式1:
复制代码代码如下所示:
VaR LIS = document.getelementbyid('ul)。GetElementsByTagName(李的);
函数FN(i){
返回函数(){
警报(一);
}
}
对于(var i = 0,len = lis.length;我< len;i++){
LIS {我} onclick= FN(我);
}
模式二:
复制代码代码如下所示:
VaR LIS = document.getelementbyid('ul)。GetElementsByTagName(李的);
对于(var i = 0,len = lis.length;我< len;i++){
(函数(i){)
LIS {我}。onclick =函数(){
警报(一);
};
})(一);
}
模式三:
复制代码代码如下所示:
VaR LIS = document.getelementbyid('ul)。GetElementsByTagName(李的);
对于(var i = 0,len = lis.length;我< len;i++){
LIS {我}。onclick=函数fn(我){
返回函数(){
警报(一);
}
}(一);
}
一口气写三种方法。相同的想法是将变量i存储为一个私有变量。我来谈谈二号路。当然,我知道其中一个是其余的,按照惯例,我们的图纸是分步分析的。
我所描述的整个代码执行的细节,而值得注意的是,每个李的onclick属性占用(功能(我){…(我)范围。当这个函数被执行时,它不会被销毁,因为它被外部李(李是窗口作用域)占据,所以作用域不会被破坏。当点击任何李时,函数(){警报(i);}将被执行,范围形成,作用域没有i,它将去(函数){…}(i),范围i被找到。最后,当参数找到i时,参数i的值将通过for循环传递。这个例子巧妙地使用闭包来存储值,并完美地解决了这个问题。
PS:刚才说的(功能(我){…(我)为什么在前面的原因是防止分号前面的语句从遗忘的分号,使Javascript犯错误时解析,如此而已。当然,以上情况是标签的原则,可能会有其他方面,如自定义属性的方式通过DOM节点找到路线和主要指标之间的关系,并用这样一种方式来加深对闭包的理解。
总结
关闭不是一个高和坏的故事。其核心是理解函数定义和调用。当函数调用时,将形成一个新的私有域。当域名被占领外,范围不会被破坏。楼主阅读很少,说错了地方请朋友们。同时,感谢您对主线的支持。