JS闭包经典实例详解


Posted in Javascript onDecember 20, 2018

本文实例讲述了JS闭包。分享给大家供大家参考,具体如下:

之前花了很多时间看书上对闭包的介绍,也看了很多人的写的关于闭包的博客,然后我就以为自己懂了。

结果,下午在一个QQ群里,有人问了这道经典的闭包问题,如下图:

JS闭包经典实例详解

我告诉他去看书上的闭包介绍。告诉他之后,我想我自己要不也写一下,反正花不了多少时间,结果花了好久怎么写也不对..............

后来看了看书上的,然后自己总结了下,觉得这次应该懂了。下次还不理解我就可以去跳楼了............

-----------------------------------分割线-----------------------------------分割线--------------------------

首先我们来了解几个概念:

立即执行函数:形如 (function(){})();的一类函数;

闭包:闭包是指有权访问另一函数作用域中的变量的函数。

作用域链:当代码执行的时候,会创建变量对象的一个作用域链....(具体百度)

我们再来看这个问题,我重新写了一个,源码如下:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>闭包经典例子详解——huansky</title>
</head>
<body>
  <div id="ttt">
    <p >000000000000000000</p>
      <br>
    <p >111111111111111111</p>
    <br>
    <p >222222222222222222</p>
  </div>
</body>
<script>
var dom=document.getElementsByTagName("p");
for(var i=0;i<dom.length;i++){
    dom[i].onclick=function(){
      console.log(i);//3
    };
}
</script>
</html>

首先,代码中的匿名函数没有变量 i,所以它必须向上查找,在全局环境中找到了 i。

for循环运行后,全局变量中的 i 变成了3。此时当你点击文字的时候,会调用其绑定的函数,而该函数运行的时候,发现自己没有 i,就会取得全局环境中的 i。

所以,最后的结果是,不管你点击那段文字,最后结果都是3。

PS:感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码,看看运行效果。

那怎么办呢?你可以用立即执行函数,看代码:

for(var i=0;i<dom.length;i++){
    dom[i].onclick=function(i){
      return function( ){
      console.log(i);
      };
    }(i);
}

我们把参数 i 作为传给立即执行函数,这样,i 的值就传给了立即执行函数的局部变量 i 了。立即执行函数会直接执行,但是其活动不会销毁,因为里面有个匿名函数。执行后局部变量 i 与全局变量 i 联系就切断了,也就是执行的时候,传进去的变量 i 是多少,立即执行函数的局部变量 i  就是多少,并且该局部变量 i 仍然没有消失,因为匿名函数的存在。

这时候,return中的匿名函数的作用域链中会有两个变量 i。当点击文本的时候,它向上搜索 i 的时候,它找到立即执行函数的局部变量 i ,就停止向上查找了,因此最后的结果就不会是全局变量 i 的值3了。

有一个方法可以检验你们有没有真的理解上面所说的,看上面的变体,代码:

for(var i=0;i<dom.length;i++){
    dom[i].onclick=function(t){
      return function( ){
      console.log(t);//1
      console.log(i);//3
      };
    }(i);
}

其实return中的匿名函数中的 t 就是立即执行函数的局部变量 i,而 i 就是 指全局变量 i,因为立即执行函数中没有变量i,只能继续向上搜索,然后就找到全局变量的 i 了。

如果看到这里,你还没有理解,有两个原因:一个原因是我表达的不够好,另一个原因是你没有完全理解前面提到的这些概念,还要继续看书。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
脚本之家贴图转换+转贴工具用到的js代码超级推荐
Apr 05 Javascript
IE浏览器PNG图片透明效果代码
Sep 02 Javascript
js实现数组去重、判断数组以及对象中的内容是否相同
Nov 29 Javascript
在Node.js中实现文件复制的方法和实例
Jun 05 Javascript
jquery访问ashx文件示例代码
Aug 11 Javascript
js倒计时抢购实例
Dec 20 Javascript
基于jQuery实现动态搜索显示功能
May 05 Javascript
canvas绘制万花筒效果(代码分享)
Jan 20 Javascript
微信小程序实现简单input正则表达式验证功能示例
Nov 30 Javascript
JS实现验证码倒计时的注册页面
Jan 02 Javascript
js实现页面多个日期时间倒计时效果
Jun 20 Javascript
js布局实现单选按钮控件
Jan 17 Javascript
JS闭包原理与应用经典示例
Dec 20 #Javascript
Mint UI组件库CheckList使用及踩坑总结
Dec 20 #Javascript
从零开始在NPM上发布一个Vue组件的方法步骤
Dec 20 #Javascript
微信小程序实现swiper切换卡内嵌滚动条不显示的方法示例
Dec 20 #Javascript
微信小程序实现的点击按钮 弹出底部上拉菜单功能示例
Dec 20 #Javascript
vue+Vue Router多级侧导航切换路由(页面)的实现代码
Dec 20 #Javascript
微信小程序module.exports模块化操作实例浅析
Dec 20 #Javascript
You might like
使用PHP和XSL stylesheets转换XML文档
2006/10/09 PHP
我的论坛源代码(五)
2006/10/09 PHP
php使用number_format函数截取小数的方法分析
2016/05/27 PHP
让GoogleCode的SVN下的HTML文件在FireFox下正常显示.
2009/05/25 Javascript
JQuery文本框高亮显示插件代码
2011/04/02 Javascript
JavaScript常用对象的方法和属性小结
2012/01/24 Javascript
JS自动缩小超出大小的图片
2012/10/12 Javascript
原生js结合html5制作小飞龙的简易跳球
2015/03/30 Javascript
JavaScript给input的value赋值引发的关于基本类型值和引用类型值问题
2015/12/07 Javascript
js基于setTimeout与setInterval实现多线程
2016/06/17 Javascript
chrome浏览器如何断点调试异步加载的JS
2016/09/05 Javascript
浅析JS中的 map, filter, some, every, forEach, for in, for of 用法总结
2017/03/29 Javascript
JS使用tofixed与round处理数据四舍五入的区别
2017/10/25 Javascript
Vue2.0子同级组件之间数据交互方法
2018/02/28 Javascript
vue-lazyload使用总结(推荐)
2018/11/01 Javascript
vuex 解决报错this.$store.commit is not a function的方法
2018/12/17 Javascript
微信小程序实现录音时的麦克风动画效果实例
2019/05/18 Javascript
openlayers实现地图弹窗
2020/09/25 Javascript
[02:07]2017国际邀请赛中国区预选赛直邀战队前瞻
2017/06/23 DOTA
[01:03:03]VP vs Mineski 2018国际邀请赛淘汰赛BO3 第一场 8.22
2018/08/23 DOTA
基于pip install django失败时的解决方法
2018/06/12 Python
python批量修改图片大小的方法
2018/07/24 Python
在python中实现强制关闭线程的示例
2019/01/22 Python
python时间日期操作方法实例小结
2020/02/06 Python
python 比较字典value的最大值的几种方法
2020/04/17 Python
澳大利亚领先的美容护肤品零售商之一:SkincareStore
2018/01/22 全球购物
潘多拉珠宝俄罗斯官方网上商店:PANDORA俄罗斯
2020/09/22 全球购物
生物技术专业求职信
2014/06/10 职场文书
幼儿园安全生产月活动总结
2014/07/05 职场文书
机关干部个人对照检查材料思想汇报
2014/09/28 职场文书
解除劳动合同协议书(样本)
2014/10/02 职场文书
六一儿童节新闻稿
2015/07/17 职场文书
歌咏比赛口号大全
2015/12/25 职场文书
同学聚会开幕词
2019/04/02 职场文书
nginx常用命令放入shell脚本详解
2021/03/31 Servers
利用Apache Common将java对象池化的问题
2022/06/16 Servers