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 相关文章推荐
Javascript实现关联数据(Linked Data)查询及注意细节
Feb 22 Javascript
JavaScript运行机制之事件循环(Event Loop)详解
Oct 10 Javascript
JS实现文字链接感应鼠标淡入淡出改变颜色的方法
Feb 26 Javascript
javascript常用的方法整理
Aug 20 Javascript
AngularJS 单元测试(一)详解
Sep 21 Javascript
微信小程序 轮播图swiper详解及实例(源码下载)
Jan 11 Javascript
jquery中封装函数传递当前元素的方法示例
May 05 jQuery
前端主流框架vue学习笔记第二篇
Jul 26 Javascript
自定义vue组件发布到npm的方法
May 09 Javascript
vue返回上一页面时回到原先滚动的位置的方法
Dec 20 Javascript
egg.js的基本使用和调用数据库的方法示例
May 18 Javascript
JS函数进阶之prototy用法实例分析
Jan 15 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
晋城吧对DiscuzX进行的前端优化要点
2010/09/05 PHP
带你了解PHP7 性能翻倍的关键
2015/11/19 PHP
PHP HTTP 认证实例详解
2016/11/03 PHP
详解php与ethereum客户端交互
2018/04/28 PHP
PHP递归遍历文件夹去除注释并压缩php源代码的方法示例
2018/05/23 PHP
PDO::beginTransaction讲解
2019/01/27 PHP
jQuery Jcrop插件实现图片选取功能
2011/11/23 Javascript
JQuery给元素添加/删除节点比如select
2013/04/02 Javascript
js中 关于undefined和null的区别介绍
2013/04/16 Javascript
JS读取XML文件示例代码
2013/11/15 Javascript
jQuery点击自身以外地方关闭弹出层的简单实例
2013/12/24 Javascript
在HTML代码中使用JavaScript代码的例子
2014/10/16 Javascript
js全选实现和判断是否有复选框选中的方法
2015/02/17 Javascript
简单的分页代码js实现
2016/05/17 Javascript
gulp-htmlmin压缩html的gulp插件实例代码
2016/06/06 Javascript
js实现百度地图定位于地址逆解析,显示自己当前的地理位置
2016/12/08 Javascript
原生JavaScript实现精美的淘宝轮播图效果示例【附demo源码下载】
2017/05/27 Javascript
Webpack打包css后z-index被重新计算的解决方法
2017/06/18 Javascript
ECMAScript6变量的解构赋值实例详解
2017/09/19 Javascript
详解node nvm进行node多版本管理
2017/10/21 Javascript
微信小程序在其他页面监听globalData中值的变化
2019/07/15 Javascript
js实现小球在页面规定的区域运动
2020/06/16 Javascript
vue商城中商品“筛选器”功能的实现代码
2020/07/01 Javascript
Angular短信模板校验代码
2020/09/23 Javascript
pandas使用apply多列生成一列数据的实例
2018/11/28 Python
Python 、Pycharm、Anaconda三者的区别与联系、安装过程及注意事项
2019/10/11 Python
pytorch中nn.Conv1d的用法详解
2019/12/31 Python
Python实现井字棋小游戏
2020/03/09 Python
Python 跨.py文件调用自定义函数说明
2020/06/01 Python
Pytorch 使用CNN图像分类的实现
2020/06/16 Python
Django限制API访问频率常用方法解析
2020/10/12 Python
基于pycharm 项目和项目文件命名规则的介绍
2021/01/15 Python
有机童装:Toby Tiger
2018/05/23 全球购物
C++如何引用一个已经定义过的全局变量
2014/08/25 面试题
动物学专业毕业生求职信
2013/10/11 职场文书
求职信格式范文
2015/03/19 职场文书