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 相关文章推荐
jquery 元素相对定位代码
Oct 15 Javascript
jQuery EasyUI API 中文文档 - NumberSpinner数值微调器使用介绍
Oct 21 Javascript
jquery中focus()函数实现当对象获得焦点后自动把光标移到内容最后
Sep 29 Javascript
jQuery无刷新上传之uploadify3.1简单使用
Jun 18 Javascript
footer定位页面底部(代码分享)
Mar 07 Javascript
详解Vue中一种简易路由传参办法
Sep 15 Javascript
Node.js使用Express.Router的方法
Nov 14 Javascript
基于input动态模糊查询的实现方法
Dec 12 Javascript
Vue.directive使用注意(小结)
Aug 31 Javascript
vue-cli中vue本地实现跨域调试接口
Jan 16 Javascript
JavaScript 严格模式(use strict)用法实例分析
Mar 04 Javascript
Vue实现Layui的集成方法步骤
Apr 10 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 常见郁闷问题答解
2006/11/25 PHP
Zend Framework教程之Zend_Form组件实现表单提交并显示错误提示的方法
2016/03/21 PHP
Ubuntu 16.04下安装PHP 7过程详解
2017/03/28 PHP
PHP date_default_timezone_set()设置时区操作实例分析
2020/05/16 PHP
基于jquery的滑动样例代码
2010/11/20 Javascript
jQuery选择器中含有空格的使用示例及注意事项
2013/08/25 Javascript
js获取某元素的class里面的css属性值代码
2014/01/16 Javascript
javascript中HTMLDOM操作详解
2014/12/11 Javascript
jQuery子窗体取得父窗体元素的方法
2015/05/11 Javascript
jQuery根据用户电脑是mac还是pc加载对应样式的方法
2015/06/26 Javascript
浅谈javascript的call()、apply()、bind()的用法
2016/02/21 Javascript
jQuery图片左右滚动代码 有左右按钮实例
2016/06/20 Javascript
JS动态遍历json中所有键值对的方法(不知道属性名的情况)
2016/12/28 Javascript
a标签置灰不可点击的实现方法
2017/02/06 Javascript
详解wow.js中各种特效对应的类名
2017/09/13 Javascript
浅谈Angular2 模块懒加载的方法
2017/10/04 Javascript
详解基于 Nuxt 的 Vue.js 服务端渲染实践
2017/10/24 Javascript
JS原型继承四步曲及原型继承图一览
2017/11/28 Javascript
原生js通过一行代码实现简易轮播图
2019/06/05 Javascript
JavaScript ES 模块的使用
2020/11/12 Javascript
[00:47]TI7不朽珍藏III——沙王不朽展示
2017/07/15 DOTA
[01:19:23]2018DOTA2亚洲邀请赛 4.5 淘汰赛 Mineski vs VG 第二场
2018/04/06 DOTA
python中的一些类型转换函数小结
2013/02/10 Python
python获取list下标及其值的简单方法
2016/09/12 Python
Python可变参数用法实例分析
2017/04/02 Python
numpy判断数值类型、过滤出数值型数据的方法
2018/06/09 Python
pyqt5 使用label控件实时显示时间的实例
2019/06/14 Python
opencv 图像礼帽和图像黑帽的实现
2020/07/07 Python
Python爬虫使用bs4方法实现数据解析
2020/08/25 Python
python实现简单的五子棋游戏
2020/09/01 Python
美国战术品牌:5.11 Tactical
2019/05/01 全球购物
《最可爱的人》教学反思
2014/02/14 职场文书
优秀英文求职信范文
2015/03/19 职场文书
2015年新教师工作总结
2015/04/28 职场文书
第一军规观后感
2015/06/12 职场文书
严以律己学习心得体会
2016/01/13 职场文书