浅谈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 相关文章推荐
jquery提升性能最佳实践小结
Dec 06 Javascript
JS删除数组元素的函数介绍
Mar 27 Javascript
基于JavaScript实现弹出框效果
Feb 19 Javascript
手机端 HTML5使用photoswipe.js仿微信朋友圈图片放大效果
Aug 25 Javascript
手机端实现Bootstrap简单图片轮播效果
Oct 13 Javascript
vue+swiper实现侧滑菜单效果
Dec 28 Javascript
Vue自定义指令实现checkbox全选功能的方法
Feb 28 Javascript
使用Vue组件实现一个简单弹窗效果
Apr 23 Javascript
vue2单元测试环境搭建
May 24 Javascript
详解为生产环境编译Angular2应用的方法
Dec 10 Javascript
详解钉钉小程序组件之自定义模态框(弹窗封装实现)
Mar 07 Javascript
js实现简单图片拖拽效果
Feb 22 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
COM in PHP (winows only)
2006/10/09 PHP
Gregarius中文日期格式问题解决办法
2008/04/22 PHP
使用php来实现网络服务
2009/09/15 PHP
php基础教程 php内置函数实例教程
2012/08/21 PHP
解析php扩展php_curl.dll不加载的解决方法
2013/06/26 PHP
PHP中Session引起的脚本阻塞问题解决办法
2014/04/08 PHP
PHP Streams(流)详细介绍及使用
2015/05/12 PHP
解决php extension 加载顺序问题
2019/08/16 PHP
jquery easyui的tabs使用时的问题
2010/03/23 Javascript
JavaScript prototype属性使用说明
2010/05/13 Javascript
JS清除选择内容的方法
2015/01/29 Javascript
贴近用户体验的Jquery日期、时间选择插件
2015/08/19 Javascript
jquery性能优化高级技巧
2015/08/24 Javascript
AngularJS中的Directive自定义一个表格
2016/01/25 Javascript
基于jquery实现无限级树形菜单
2016/03/22 Javascript
Bootstrap table两种分页示例
2016/12/23 Javascript
js自制图片放大镜功能
2017/01/24 Javascript
基于JS实现翻书效果的页面切换样式
2017/02/16 Javascript
基于构造函数的五种继承方法小结
2017/07/27 Javascript
vue2.0与bootstrap3实现列表分页效果
2017/11/28 Javascript
angularjs http与后台交互的实现示例
2018/12/21 Javascript
layui 富文本图片上传接口与普通按钮 文件上传接口的例子
2019/09/23 Javascript
python正则分析nginx的访问日志
2017/01/17 Python
Python3+django2.0+apache2+ubuntu14部署网站上线的方法
2018/07/07 Python
python 自动去除空行的实例
2018/07/24 Python
Pycharm如何打断点的方法步骤
2019/06/13 Python
python bluetooth蓝牙信息获取蓝牙设备类型的方法
2019/11/29 Python
HelloFresh奥地利:立即订购烹饪盒
2019/02/22 全球购物
Tea Collection官网:一家位于旧金山的童装公司
2020/08/07 全球购物
夜大毕业生自我鉴定
2013/10/31 职场文书
商场拾金不昧表扬信
2014/01/13 职场文书
开学典礼决心书
2014/03/11 职场文书
医院搬迁方案
2014/06/14 职场文书
实习单位指导教师评语
2014/12/30 职场文书
浅谈由position属性引申的css进阶讨论
2021/05/25 HTML / CSS
tensorflow中的梯度求解及梯度裁剪操作
2021/05/26 Python