浅谈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 相关文章推荐
javascript+xml技术实现分页浏览
Jul 27 Javascript
JavaScript中的prototype使用说明
Apr 13 Javascript
js location.replace与location.reload的区别
Sep 08 Javascript
Jquery实现页面加载时弹出对话框代码
Apr 19 Javascript
提取字符串中年月日的函数代码
Nov 05 Javascript
jquery控制select的text/value值为选中状态
Jun 03 Javascript
纯js实现div内图片自适应大小(已测试,兼容火狐)
Jun 16 Javascript
jQuery中attr()和prop()在修改checked属性时的区别
Jul 18 Javascript
深入理解JavaScript系列(18):面向对象编程之ECMAScript实现
Mar 05 Javascript
全面解析bootstrap格子布局
May 22 Javascript
使用node.js实现微信小程序实时聊天功能
Aug 13 Javascript
vue+Element-ui实现分页效果实例代码详解
Dec 10 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
来自PHP.NET的入门教程
2006/10/09 PHP
Yii2隐藏frontend/web和backend/web的方法
2015/12/12 PHP
yii框架结合charjs统计上一年与当前年数据的方法示例
2020/04/04 PHP
jquery text,radio,checkbox,select操作实现代码
2009/07/09 Javascript
JavaScript面向对象设计二 构造函数模式
2011/12/20 Javascript
javascript 自定义回调函数示例代码
2014/09/26 Javascript
js实现滑动触屏事件监听的方法
2015/05/05 Javascript
javascript实现10个球随机运动、碰撞实例详解
2015/07/08 Javascript
jquery获取url参数及url加参数的方法
2015/10/26 Javascript
javascript正则表达式之分组概念与用法实例
2016/06/16 Javascript
js转换对象为xml
2017/02/17 Javascript
ionic2屏幕适配实现适配手机、平板等设备的示例代码
2017/08/11 Javascript
nginx配置React静态页面的方法教程
2017/11/03 Javascript
原生js+cookie实现购物车功能的方法分析
2017/12/21 Javascript
在Vue项目中使用d3.js的实例代码
2018/05/01 Javascript
开发Node CLI构建微信小程序脚手架的示例
2020/03/27 Javascript
[03:02]2014DOTA2西雅图邀请赛 让队员自己告诉你DK NAVI备战情况
2014/07/08 DOTA
python str与repr的区别
2013/03/23 Python
Python中List.index()方法的使用教程
2015/05/20 Python
python实现寻找最长回文子序列的方法
2018/06/02 Python
python实现归并排序算法
2018/11/22 Python
使用pyshp包进行shapefile文件修改的例子
2019/12/06 Python
python 类之间的参数传递方式
2019/12/20 Python
使用python快速实现不同机器间文件夹共享方式
2019/12/22 Python
PyCharm+PyQt5+QtDesigner配置详解
2020/08/12 Python
Python grpc超时机制代码示例
2020/09/14 Python
详解使用HTML5 Canvas创建动态粒子网格动画
2016/12/14 HTML / CSS
贝佳斯官方网站:Borghese
2020/05/08 全球购物
电子信息毕业生自荐信
2013/11/16 职场文书
调解员先进事迹材料
2014/02/07 职场文书
管理学院毕业生自荐信范文
2014/03/10 职场文书
小学一年级学生评语大全
2014/12/25 职场文书
2015年银行个人工作总结
2015/05/14 职场文书
热血教师观后感
2015/06/10 职场文书
2015迎新晚会开场白
2015/07/17 职场文书
小学生纪律委员竞选稿
2015/11/19 职场文书