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 相关文章推荐
LazyLoad 延迟加载(按需加载)
May 31 Javascript
JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)
Dec 17 Javascript
javascript获取文档坐标和视口坐标
May 26 Javascript
jQuery旋转木马式幻灯片轮播特效
Dec 04 Javascript
JavaScript+html5 canvas绘制的圆弧荡秋千效果完整实例
Jan 26 Javascript
通过jsonp获取json数据实现AJAX跨域请求
Jan 22 Javascript
微信小程序之蓝牙的链接
Sep 26 Javascript
浅谈Node.js之异步流控制
Oct 25 Javascript
Vue项目部署的实现(阿里云+Nginx代理+PM2)
Mar 26 Javascript
深入浅析nuxt.js基于ssh的vue通用框架
May 21 Javascript
vue+vant实现商品列表批量倒计时功能
Jan 13 Javascript
vuex(vue状态管理)的特殊应用案例分享
Mar 03 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简单对象与数组的转换函数代码(php多层数组和对象的转换)
2011/05/18 PHP
深入php var_dump()函数的详解
2013/06/05 PHP
Yii使用ajax验证显示错误messagebox的解决方法
2014/12/03 PHP
php运行报错Call to undefined function curl_init()的最新解决方法
2016/11/20 PHP
jQuery ajax+PHP实现的级联下拉列表框功能示例
2019/02/12 PHP
js下弹出窗口的变通
2007/04/18 Javascript
Prototype 学习 工具函数学习($方法)
2009/07/12 Javascript
JavaScript 上万关键字瞬间匹配实现代码
2013/07/07 Javascript
JS实现程序暂停与继续功能代码解读
2013/10/10 Javascript
js从Cookies里面取值的简单实现
2014/06/30 Javascript
JavaScript检测弹出窗口是否已经关闭的方法
2015/03/24 Javascript
js正则匹配出所有图片及图片地址src的方法
2015/06/08 Javascript
jquery实现可旋转可拖拽的文字效果代码
2016/01/27 Javascript
Bootstrap表单布局样式源代码
2016/07/04 Javascript
jQuery实现checkbox列表的全选、反选功能
2016/11/24 Javascript
详解Angular中的自定义服务Service、Provider以及Factory
2017/04/22 Javascript
ES6新特性:使用export和import实现模块化详解
2017/07/31 Javascript
Angular自定义组件实现数据双向数据绑定的实例
2017/12/11 Javascript
Vue组件化开发思考
2018/02/02 Javascript
js字符串倒序的实例代码
2018/11/30 Javascript
JavaScript函数式编程(Functional Programming)纯函数用法分析
2019/05/22 Javascript
Layui Table js 模拟选中checkbox的例子
2019/09/03 Javascript
javascript 设计模式之组合模式原理与应用详解
2020/04/08 Javascript
vue中使用echarts的示例
2021/01/03 Vue.js
Python 函数基础知识汇总
2018/03/09 Python
对python实现模板生成脚本的方法详解
2019/01/30 Python
python和mysql交互操作实例详解【基于pymysql库】
2019/06/04 Python
Python字典实现伪切片功能
2020/10/28 Python
利用HTML5+css3+jquery+weui实现仿微信聊天界面功能
2018/01/08 HTML / CSS
跑步、骑行和铁人三项的高性能眼镜和服装:ROKA
2018/07/06 全球购物
文明风采获奖感言
2014/02/18 职场文书
班主任班级寄语大全
2014/04/04 职场文书
南京青奥会口号
2014/06/12 职场文书
通知函格式范文
2015/04/27 职场文书
思想工作总结范文
2015/08/12 职场文书
新手必备之MySQL msi版本下载安装图文详细教程
2021/05/21 MySQL