轻松理解JavaScript闭包


Posted in Javascript onMarch 14, 2017

摘要

闭包机制是JavaScript的重点和难点,本文希望能帮助大家轻松的学习闭包

一、什么是闭包?

闭包就是可以访问另一个函数作用域中变量的函数。

下面列举出常见的闭包实现方式,以例子讲解闭包概念

function f1(){

var n=999;


nAdd=function(){n+=1}


function f2(){



alert(n);


}


return f2;

}

var result=f1();

result(); // 999

nAdd();

result(); // 1000

f1是f2的父函数,而f2被赋给了一个全局变量(return的值),这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收,这便形成了闭包。

因此,可以这么理解。闭包机制就是,如果A函数引用了另一个函数B的变量,但是B返回后A仍没有返回,仍存在,因为A的引用,所以B的所有局部变量并不会随B退出而注销,会一直存在,直到A注销。此时A就是闭包。

二、闭包的this指针

闭包通常在全局环境调用的,所以this通常指向window,具体情况还是需要视执行环境而言,总之this指向执行环境。

若需要闭包的this指向闭包的包含对象,则需要将包含对象的this作为变量传进闭包。

三、使用闭包的注意点

  1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
  2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

四、解决一道闭包常见面试题

问题:

function onMyLoad(){
  /*
  抛出问题:
  此题的目的是想每次点击对应目标时弹出对应的数字下标 0~4,但实际是无论点击哪个目标都会弹出数字5
  问题所在:
  arr 中的每一项的 onclick 均为一个函数实例(Function 对象),这个函数实例也产生了一个闭包域,
  这个闭包域引用了外部闭包域的变量,其 function scope 的 closure 对象有个名为 i 的引用,
  外部闭包域的私有变量内容发生变化,内部闭包域得到的值自然会发生改变
  */
  var arr = document.getElementsByTagName("p");
  for(var i = 0; i < arr.length;i++){
  arr[i].onclick = function(){
   alert(i);
  }
  }
 }

解决方法

1、在外面再加一层函数,将i作为函数参数传进来,这样每次保存的是函数内部的变量,与外部i不是同一个内存空间,而每次调用函数都会生成一个局部变量,所以可以保证每次保存的值互不影响。

for(var i = 0; i<arr.length;i++){
 arr[i].onclick = (function(arg){
  return function () {
   alert(arg);
  }
 })(i);
}

2、用ES6新特let,将for循环的var i改成let i,这样当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
取得传值的函数
Oct 27 Javascript
一个简单的js树形菜单
Dec 09 Javascript
鼠标选择动态改变网页背景颜色的JS代码
Dec 10 Javascript
jQuery 仿百度输入标签插件附效果图
Jul 04 Javascript
使用FlexiGrid实现Extjs表格效果方法分享
Dec 16 Javascript
基于JS实现EOS隐藏错误提示层代码
Apr 25 Javascript
CKEditor无法验证的解决方案(js验证+jQuery Validate验证)
May 09 Javascript
Spring MVC中Ajax实现二级联动的简单实例
Jul 06 Javascript
js实现砖头在页面拖拉效果
Nov 20 Javascript
js放大镜放大购物图片效果
Jan 18 Javascript
JS实现的集合去重,交集,并集,差集功能示例
Mar 13 Javascript
vue axios封装httpjs,接口公用配置拦截操作
Aug 11 Javascript
微信小程序 页面跳转及数据传递详解
Mar 14 #Javascript
JavaScript ES6中export、import与export default的用法和区别
Mar 14 #Javascript
微信小程序 动态绑定数据及动态事件处理
Mar 14 #Javascript
Vue 2.0+Vue-router构建一个简单的单页应用(附源码)
Mar 14 #Javascript
vuejs响应用户事件(如点击事件)
Mar 14 #Javascript
微信小程序 在线支付功能的实现
Mar 14 #Javascript
JS和canvas实现俄罗斯方块
Mar 14 #Javascript
You might like
ThinkPHP使用心得分享-分页类Page的用法
2014/05/15 PHP
微信封装的调用微信签名包的类库
2017/06/08 PHP
thinkPHP微信分享接口JSSDK用法实例
2017/07/07 PHP
类之Prototype.js学习
2007/06/13 Javascript
用js实现计算加载页面所用的时间
2010/04/02 Javascript
发布一个基于javascript的动画类 Fx.js
2010/11/05 Javascript
javascript-简单的计算器实现步骤分解(附图)
2013/05/30 Javascript
利用jquery.qrcode在页面上生成二维码且支持中文
2014/02/12 Javascript
JS完整获取IE浏览器信息包括类型、版本、语言等等
2014/05/22 Javascript
jquery实现动态操作select选中
2015/02/11 Javascript
jQuery实现类似淘宝网图片放大效果的方法
2015/07/08 Javascript
基于jquery实现无限级树形菜单
2016/03/22 Javascript
jQuery实现表格行和列的动态添加与删除方法【测试可用】
2016/08/01 Javascript
JS实现title标题栏文字不间断滚动显示效果
2016/09/07 Javascript
javascript自执行函数
2017/02/10 Javascript
详谈AngularJs 控制器、数据绑定、作用域
2017/07/09 Javascript
vue.js前后端数据交互之提交数据操作详解
2018/04/24 Javascript
jQuery实现table表格信息的展开和缩小功能示例
2018/07/21 jQuery
Vue中用props给data赋初始值遇到的问题解决
2018/11/27 Javascript
微信小程序自定义toast组件的方法详解【含动画】
2019/05/11 Javascript
vue移动端弹起蒙层滑动禁止底部滑动操作
2020/07/22 Javascript
Nodejs + sequelize 实现增删改查操作
2020/11/07 NodeJs
对于Python装饰器使用的一些建议
2015/06/03 Python
使用apidocJs快速生成在线文档的实例讲解
2018/02/07 Python
Python实现简易过滤删除数字的方法小结
2019/01/09 Python
python3.x提取中文的正则表达式示例代码
2019/07/23 Python
Python object类中的特殊方法代码讲解
2020/03/06 Python
python爬虫线程池案例详解(梨视频短视频爬取)
2021/02/20 Python
StubHub希腊:购买体育赛事、音乐会和剧院门票
2019/08/03 全球购物
酒店出纳岗位职责
2013/12/29 职场文书
学校采购员岗位职责
2014/01/02 职场文书
求职信模板怎么做
2014/01/26 职场文书
飘柔洗发水广告词
2014/03/14 职场文书
2014年大学教师工作总结
2014/12/02 职场文书
2016年会领导致辞稿
2015/07/29 职场文书
Win11运行育碧游戏总是崩溃怎么办 win11玩育碧游戏出现性能崩溃的解决办法
2022/04/06 数码科技