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文本框高亮显示插件代码
Apr 02 Javascript
Jquery Uploadify上传带进度条的简单实例
Feb 12 Javascript
jquery中one()方法的用法实例
Jan 16 Javascript
JavaScript仿flash遮罩动画效果
Jun 15 Javascript
Js获取当前日期时间及格式化代码
Sep 17 Javascript
概述VUE2.0不可忽视的很多变化
Sep 25 Javascript
如何使用bootstrap框架 bootstrap入门必看!
Apr 13 Javascript
JS作用域链详解
Jun 26 Javascript
jQuery.validate.js表单验证插件的使用代码详解
Oct 22 jQuery
小程序测试后台服务的方法(ngrok)
Mar 08 Javascript
layui radio单选限制下一个radio单选的实例
Sep 03 Javascript
layer插件实现在弹出层中弹出一警告提示并关闭弹出层的方法
Sep 24 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数组函数序列 之shuffle()和array_rand() 随机函数使用介绍
2011/10/29 PHP
微信支付PHP SDK ―― 公众号支付代码详解
2016/09/13 PHP
PHP实现超简单的SSL加密解密、验证及签名的方法示例
2017/08/28 PHP
javascript实现上传图片前的预览(TX的面试题)
2007/08/20 Javascript
LazyLoad 延迟加载(按需加载)
2010/05/31 Javascript
JavaScript中遍历对象的property的3种方法介绍
2014/12/30 Javascript
JavaScript 异常处理 详解
2015/02/06 Javascript
javascript实现当前页导航激活的方法
2015/02/27 Javascript
HTML5游戏引擎LTweenLite实现的超帅动画效果(附demo源码下载)
2016/01/26 Javascript
JavaScript实现点击单元格改变背景色的方法
2016/02/12 Javascript
PHP+jquery+ajax实现分页
2016/12/09 Javascript
微信小程序使用image组件显示图片的方法【附源码下载】
2017/12/08 Javascript
postman+json+springmvc测试批量添加实例
2018/03/31 Javascript
详解使用angular框架离线你的应用(pwa指南)
2019/01/31 Javascript
Node.js中console.log()输出彩色字体的方法示例
2019/12/01 Javascript
JavaScript鼠标拖拽事件详解
2020/04/03 Javascript
[01:27:44]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Aster BO3 第一场 1月24日
2021/03/11 DOTA
[01:01:52]DOTA2-DPC中国联赛正赛 iG vs LBZS BO3 第一场 3月4日
2021/03/11 DOTA
Python3使用PyQt5制作简单的画板/手写板实例
2017/10/19 Python
python opencv检测目标颜色的实例讲解
2018/04/02 Python
解决新版Pycharm中Matplotlib图像不在弹出独立的显示窗口问题
2019/01/15 Python
Python with用法:自动关闭文件进程
2019/07/10 Python
深入浅析Python 函数注解与匿名函数
2020/02/24 Python
django 数据库 get_or_create函数返回值是tuple的问题
2020/05/15 Python
基于zepto的插件之移动端无缝向上滚动并上下触摸滑动实例代码
2016/12/20 HTML / CSS
新大陆软件面试题
2016/11/24 面试题
进程的查看和调度分别使用什么命令
2013/12/14 面试题
护理学毕业生自荐信
2013/10/02 职场文书
幼儿园国庆节活动方案
2014/02/01 职场文书
群众路线教育实践活动心得体会(四风)
2014/11/03 职场文书
2015年社区矫正工作总结
2015/04/21 职场文书
培根随笔读书笔记
2015/07/01 职场文书
情感电台广播稿
2015/08/18 职场文书
mysql 数据插入优化方法之concurrent_insert
2021/07/01 MySQL
Redis集群新增、删除节点以及动态增加内存的方法
2021/09/04 Redis
win11怎么消除图标小盾牌?win11消除图标小盾牌解决方法
2022/08/05 数码科技