浅谈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 animate图片模向滑动示例代码
Jan 26 Javascript
JS上传图片前的限制包括(jpg jpg gif及大小高宽)等
Dec 19 Javascript
jQuery动态效果显示人物结构关系图的方法
May 07 Javascript
IE和Firefox之间在JavaScript语法上的差异
Apr 22 Javascript
bootstarp modal框居中显示的实现代码
Feb 18 Javascript
JavaScript实现256色转灰度图
Feb 22 Javascript
JavaScrpt的面向对象全面解析
May 09 Javascript
Angular获取手机验证码实现移动端登录注册功能
May 17 Javascript
Vue中的ref作用详解(实现DOM的联动操作)
Aug 21 Javascript
Bootstrap 实现表格样式、表单布局的实例代码
Dec 09 Javascript
详解微信小程序缓存--缓存时效性
May 02 Javascript
vue-cli webpack配置文件分析
May 20 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的String类代码
2010/04/20 PHP
对text数据类型不支持代码页转换 从: 1252 到: 936
2011/04/23 PHP
php模拟js函数unescape的函数代码
2012/10/20 PHP
php计算整个mysql数据库大小的方法
2015/06/19 PHP
Firefox中beforeunload事件的实现缺陷浅析
2012/05/03 Javascript
jQuery插件实现表格隔行换色且感应鼠标高亮行变色
2013/09/22 Javascript
使用JQ来编写最基本的淡入淡出效果附演示动画
2014/10/31 Javascript
浅谈JavaScript 覆盖原型以及更改原型
2016/08/31 Javascript
AngularJS使用ng-inlude指令加载页面失败的原因与解决方法
2017/01/19 Javascript
ES6新特性四:变量的解构赋值实例
2017/04/21 Javascript
在Vue组件上动态添加和删除属性方法
2018/02/23 Javascript
详解vue-property-decorator使用手册
2019/07/29 Javascript
JavaScript自动生成 年月范围 选择功能完整示例【基于jQuery插件】
2019/09/03 jQuery
nodejs实现UDP组播示例方法
2019/11/04 NodeJs
vue模块移动组件的实现示例
2020/05/20 Javascript
基于Linux系统中python matplotlib画图的中文显示问题的解决方法
2017/06/15 Python
Python:Scrapy框架中Item Pipeline组件使用详解
2017/12/27 Python
Flask模拟实现CSRF攻击的方法
2018/07/24 Python
Python日期时间模块datetime详解与Python 日期时间的比较,计算实例代码
2018/09/14 Python
python中struct模块之字节型数据的处理方法
2019/08/27 Python
python+selenium+chromedriver实现爬虫示例代码
2020/04/10 Python
python自动化测试三部曲之request+django实现接口测试
2020/10/07 Python
用CSS3和table标签实现一个圆形轨迹的动画的示例代码
2019/01/17 HTML / CSS
西班牙在线宠物商店:zooplus.es
2017/02/24 全球购物
瑞典廉价机票预订网站:Seat24
2018/06/19 全球购物
Omio英国:搜索并比较便宜的巴士、火车和飞机
2019/08/27 全球购物
如何设置Java的运行环境
2013/04/05 面试题
高三毕业典礼演讲稿
2014/05/13 职场文书
低碳环保口号
2014/06/12 职场文书
博士生导师推荐信
2014/07/08 职场文书
幼儿教师暑期培训方案
2014/08/27 职场文书
软件测试专业推荐信
2014/09/18 职场文书
小学五一劳动节活动总结
2015/02/09 职场文书
教师工作能力自我评价
2015/03/04 职场文书
旗帜观后感
2015/06/08 职场文书
Python 多线程处理任务实例
2021/11/07 Python