浅谈javascript中的闭包


Posted in Javascript onMay 13, 2015

很长一段时间不理解闭包,后来了解了作用域,以及this相关问题才理解了闭包相关知识。
闭包(closure),也是面试题常客。简单点来说就是函数嵌套函数。

函数作为返回值:

function foo () {
  var a = 1;
  return function () {
   a++;
   console.log(a);
  }
}
var aaa = foo();
aaa(); //2
aaa(); //3

其实这个代码不难理解,aaa是指向foo()返回的一个新函数,但是在这个函数里面引用了a变量,所以当执行完foo函数时,变量a还存在内存中不释放。即a分别为2和3。

函数作为参数:

var a = 10;
function foo () {
console.log(a);
}
function aaa(fn) {
 var a = 100;
 fn();
}
aaa(foo);

按照我以前的理解,当执行在aaa函数里面执行fn函数,那么如果自身没有a变量,就去父级作用域找a变量,此处是100,那结果是100吗?

可惜答案不是,在这里结果是10,王福朋老师的博客讲的比较好,他说要去创建这个函数的作用域取值,而不是“父作用域”。

闭包的使用场景

因为本人还比较菜鸟,在这里取一个简单例子。当点击li的时候弹出li在ul中所处的位置即索引值。

html代码:

<ul>
  <li>001</li>
  <li>002</li>
  <li>003</li>
</ul>

js代码:

示例 1:
请看下面的代码,运行后发现,无论点击那个li,结果都是3了。

var aLi = document.getElementsByTagName('li');
for (var i = 0; i<aLi.length; i++) {
  aLi[i].onclick = function() {
   alert(i);
  }
}

因为在匿名函数里面并没有i变量,所以当for结束后,我们再去点击页面的li标签,此时i早就是3了。

示例 2:

aLi[i].onclick = (function(i){
    return function(){
      alert(i);
    }
  })(i);

这次的做法是把函数当返回值,通过自执行函数的参数,把变量i传进去,然后因为返回函数要引用这个i变量,所以当for循环结束也不会释放i变量。即在内存中保存了i变量的值。基于这样的原理,很容易在低版本ie中造成内存泄露。

示例 3:

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

这个原理和上面大同小异。

小米前端闭包面试题:

function repeat (func, times, wait) {
} //这个函数能返回一个新函数,比如这样用

var repeatedFun = repeat(alert, 10, 5000)
//调用这个 repeatedFun ("hellworld")

//会alert十次 helloworld, 每次间隔5秒

我的答案:

function repeat (func, times, wait) {
  return function(str) {
    while (times >0) {
      setTimeout(function(){
        func(str);
      },wait);
      times--;
    }
  }
}

var repeatedFun = repeat(alert, 10, 100);
repeatedFun ("hellworld");

以上所述就是本文的全部内容了,希望对大家学习javascript闭包能够有所帮助。

Javascript 相关文章推荐
FireFox下XML对象转化成字符串的解决方法
Dec 09 Javascript
jquery创建一个ajax关键词数据搜索实现思路
Feb 26 Javascript
Js实现当前点击a标签变色突出显示其他a标签回复原色
Nov 27 Javascript
一个jquery实现的不错的多行文字图片滚动效果
Sep 28 Javascript
jQuery常用数据处理方法小结
Feb 20 Javascript
javascript实现动态标签云
Oct 16 Javascript
jQuery插件实现带圆点的焦点图片轮播切换
Jan 18 Javascript
jQuery Validate表单验证插件 添加class属性形式的校验
Jan 18 Javascript
Angularjs 实现分页功能及示例代码
Sep 14 Javascript
利用jQuery.Validate异步验证用户名是否存在(推荐)
Dec 09 Javascript
Javascript实现倒计时(防页面刷新)实例
Dec 13 Javascript
React Native之ListView实现九宫格效果的示例
Aug 02 Javascript
jQuery构造函数init参数分析续
May 13 #Javascript
jQuery构造函数init参数分析
May 13 #Javascript
CSS+JS实现点击文字弹出定时自动关闭DIV层菜单的方法
May 12 #Javascript
JavaScript实现DIV层拖动及动态增加新层的方法
May 12 #Javascript
js实现带按钮的上下滚动效果
May 12 #Javascript
js验证上传图片的方法
May 12 #Javascript
js中setTimeout()与clearTimeout()用法实例浅析
May 12 #Javascript
You might like
QQ登录 PHP OAuth示例代码
2011/07/20 PHP
PHP将MySQL的查询结果转换为数组并用where拼接的示例
2016/05/13 PHP
浅谈PHP表单提交(POST&amp;GET&amp;URL编/解码)
2017/04/03 PHP
关于Curl在Swoole协程中的解决方案详析
2019/09/12 PHP
仿校内登陆框,精美,给那些很厉害但是没有设计天才的程序员
2008/11/24 Javascript
Iframe 自适应高度并实时监控高度变化的js代码
2009/10/30 Javascript
Extjs优化(一)删除冗余代码提高运行速度
2013/04/15 Javascript
jQuery判断复选框是否勾选的原理及示例
2014/05/21 Javascript
浅谈JavaScript字符串与数组
2015/06/03 Javascript
jQuery添加和删除指定标签的方法
2015/12/16 Javascript
JavaScript数据类型学习笔记
2016/01/25 Javascript
javascript三种代码注释方法
2016/06/02 Javascript
Bootstrap实现带暂停功能的轮播组件(推荐)
2016/11/25 Javascript
jQuery日程管理插件fullcalendar使用详解
2017/01/07 Javascript
原生js实现简单的模态框示例
2017/09/08 Javascript
jquery一键控制checkbox全选、反选或全不选
2017/10/16 jQuery
Angular CLI在Angular项目中如何使用scss详解
2018/04/10 Javascript
[13:18]《一刀刀一天》之DOTA全时刻21:详解TI新赛制 A队再露獠牙
2014/06/24 DOTA
在Django框架中设置语言偏好的教程
2015/07/27 Python
Python基础之字典常见操作经典实例详解
2020/02/26 Python
Python运行异常管理解决方案
2020/03/09 Python
Python GUI编程学习笔记之tkinter控件的介绍及基本使用方法详解
2020/03/30 Python
总结Pyinstaller的坑及终极解决方法(小结)
2020/09/21 Python
html5使用canvas画三角形
2014/12/15 HTML / CSS
WoolOvers澳洲官方网站:英国针织服装公司
2018/05/13 全球购物
欧姆龙医疗欧洲有限公司:Omron Healthcare Europe B.V
2020/06/13 全球购物
认错检讨书
2014/10/02 职场文书
先进单位申报材料
2014/12/25 职场文书
2015年收银工作总结范文
2015/04/01 职场文书
2015年幼儿园班主任工作总结
2015/05/12 职场文书
上甘岭观后感
2015/06/10 职场文书
小学生组织委员竞选稿
2015/11/21 职场文书
2019年大学生职业生涯规划书最新范文
2019/03/25 职场文书
创业计划书之旅游网站
2019/09/06 职场文书
python unittest单元测试的步骤分析
2021/08/02 Python
python多线程方法详解
2022/01/18 Python