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自带函数备忘 数组
Dec 29 Javascript
基于JavaScript实现网页倒计时自动跳转代码
Dec 28 Javascript
深入解析jQuery中Deferred的deferred.promise()方法
May 03 Javascript
js绘制购物车抛物线动画
Nov 18 Javascript
js 获取元素所有兄弟节点的实现方法
Sep 06 Javascript
Actionscript与javascript交互实例程序(修改)
Sep 22 Javascript
jquery实现图片列表鼠标移入微动
Dec 01 Javascript
详解从Node.js的child_process模块来学习父子进程之间的通信
Mar 27 Javascript
vue2.0路由切换后页面滚动位置不变BUG的解决方法
Mar 14 Javascript
nuxt配置通过指定IP和端口访问的实现
Jan 08 Javascript
es6函数之尾递归用法实例分析
Apr 25 Javascript
原生js实现弹窗消息动画
Nov 20 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
解析php中call_user_func_array的作用
2013/06/07 PHP
PHP获取MySql新增记录ID值的3种方法
2014/06/24 PHP
php实现网页缓存的工具类分享
2015/07/14 PHP
一键生成各种尺寸Icon的php脚本(实例)
2017/02/08 PHP
利用ajax和PHP实现简单的流程管理
2017/03/23 PHP
PHP中递归的实现实例详解
2017/11/14 PHP
PDO::getAvailableDrivers讲解
2019/01/28 PHP
PHP设计模式之数据访问对象模式(DAO)原理与用法实例分析
2019/12/12 PHP
用javascript实现给图片加链接
2007/08/15 Javascript
10个基于Jquery的幻灯片插件教程
2010/10/29 Javascript
javascript中window.event事件用法详解
2012/12/11 Javascript
JS实现两个大数(整数)相乘
2014/04/28 Javascript
跟我学Nodejs(二)--- Node.js事件模块
2014/05/21 NodeJs
javascript正则表达式使用replace()替换手机号的方法
2015/01/19 Javascript
javascript判断网页是关闭还是刷新
2015/09/12 Javascript
animate 实现滑动切换效果【实例代码】
2016/05/05 Javascript
vue-cli的webpack模板项目配置文件分析
2017/04/01 Javascript
vue.js移动端tab组件的封装实践实例
2017/06/30 Javascript
ES6 新增的创建数组的方法(小结)
2019/08/01 Javascript
JS pushlet XMLAdapter适配器用法案例解析
2020/10/16 Javascript
布同自制Python函数帮助查询小工具
2011/03/13 Python
Python标准库之collections包的使用教程
2017/04/27 Python
Python+Socket实现基于UDP协议的局域网广播功能示例
2017/08/31 Python
分享一下如何编写高效且优雅的 Python 代码
2017/09/07 Python
Python处理命令行参数模块optpars用法实例分析
2018/05/31 Python
Python学习笔记之自定义函数用法详解
2019/06/08 Python
Python短信轰炸的代码
2020/03/25 Python
OpenCV实现机器人对物体进行移动跟随的方法实例
2020/11/09 Python
java关于string最常出现的面试题整理
2021/01/18 Python
一款基于css3麻将筛子3D翻转特效的实例教程
2014/12/31 HTML / CSS
Can a struct inherit from another struct? (结构体能继承结构体吗)
2016/09/25 面试题
后备干部培训方案
2014/05/22 职场文书
2015年医院后勤工作总结
2015/05/20 职场文书
Mysql基础之常见函数
2021/04/22 MySQL
如何利用opencv判断两张图片是否相同详解
2021/07/07 Python