浅谈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 作用域使用说明
Aug 13 Javascript
实用的JS正则表达式(手机号码/IP正则/邮编正则/电话等)
Jan 11 Javascript
Javascript中的包装类型介绍
Apr 02 Javascript
JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)
Sep 05 Javascript
利用js编写响应式侧边栏
Sep 17 Javascript
JS生成和下载二维码的代码
Dec 07 Javascript
jQuey将序列化对象在前台显示地实现代码(方法总结)
Dec 13 Javascript
js实现炫酷的左右轮播图
Jan 18 Javascript
JS设置CSS样式的方式汇总
Jan 21 Javascript
JS基于正则表达式实现的密码强度验证功能示例
Sep 21 Javascript
js实现数据导出为EXCEL(支持大量数据导出)
Mar 31 Javascript
element-ui中dialog弹窗关闭按钮失效的解决
Sep 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
东芝TOSHIBA RP-F11电路分析
2021/03/02 无线电
php实现utf-8和GB2312编码相互转换函数代码
2013/02/07 PHP
php字符串截取的简单方法
2013/07/04 PHP
php绘图之加载外部图片的方法
2015/01/24 PHP
php简单实现多字节字符串翻转的方法
2015/03/31 PHP
微信公众号之主动给用户发送消息功能
2019/06/22 PHP
javascript 学习笔记(一)DOM基本操作
2011/04/08 Javascript
js window.open弹出新的网页窗口
2014/01/16 Javascript
jQuery手动点击实现图片轮播特效
2020/04/20 Javascript
Vue.js每天必学之内部响应式原理探究
2016/09/07 Javascript
JavaScript的变量声明提升问题浅析(Hoisting)
2016/11/30 Javascript
nodejs和php实现图片访问实时处理
2017/01/05 NodeJs
JavaScript禁用右键单击优缺点分析
2019/01/20 Javascript
微信小程序实现工作时间段选择
2019/02/15 Javascript
JavaScript中十种一步拷贝数组的方法实例详解
2019/04/22 Javascript
Vue 3.x+axios跨域方案的踩坑指南
2019/07/04 Javascript
Vue在chrome44偶现点击子元素事件无法冒泡的解决方法
2019/12/15 Javascript
js实现鼠标点击飘爱心效果
2020/08/19 Javascript
js 执行上下文和作用域的相关总结
2021/02/08 Javascript
Python中的Numpy入门教程
2014/04/26 Python
浅谈python中requests模块导入的问题
2018/05/18 Python
python递归函数绘制分形树的方法
2018/06/22 Python
Python+OpenCV实现图像融合的原理及代码
2018/12/03 Python
Python爬虫使用代理IP的实现
2019/10/27 Python
python画蝴蝶曲线图的实例
2019/11/21 Python
Python用input输入列表的实例代码
2020/02/07 Python
CSS3线性渐变简单实现以及该属性在浏览器中的不同
2012/12/12 HTML / CSS
用HTML5制作一个简单的桌球游戏的教程
2015/05/12 HTML / CSS
详解HTML5中download属性的应用
2015/08/06 HTML / CSS
C#的几个面试问题
2016/05/22 面试题
学习党章思想汇报
2014/01/07 职场文书
文明礼仪小标兵事迹
2014/01/12 职场文书
迎八一活动主题
2014/01/31 职场文书
《草原》教学反思
2014/02/15 职场文书
长城导游词400字
2015/01/30 职场文书
幼儿园教师自我评价
2015/03/04 职场文书