浅谈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改变CSS样式(局部和全局)
Dec 18 Javascript
JavaScript截取字符串的2个函数介绍
Aug 27 Javascript
javascript实现数独解法
Mar 14 Javascript
js+css实现有立体感的按钮式文字竖排菜单效果
Sep 01 Javascript
jQuery移除或禁用html元素点击事件常用方法小结
Feb 10 Javascript
前端开发之CSS原理详解
Mar 11 Javascript
关于vue.extend和vue.component的区别浅析
Aug 16 Javascript
微信小程序-getUserInfo回调的实例详解
Oct 27 Javascript
JS非行间样式获取函数的实例代码
Jun 05 Javascript
深入浅析javascript函数中with
Oct 28 Javascript
vue实现的仿淘宝购物车功能详解
Jan 27 Javascript
vue组件中传值EventBus的使用及注意事项说明
Nov 16 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
DC漫画《蝙蝠侠和猫女》图透 猫女怀孕老爷当爹
2020/04/09 欧美动漫
php 深入理解strtotime函数的使用详解
2013/05/23 PHP
php 读取文件头判断文件类型的实现代码
2013/08/05 PHP
PHP @ at 记号的作用示例介绍
2014/10/10 PHP
PHP array_key_exists检查键名或索引是否存在于数组中的实现方法
2016/06/13 PHP
PHP+mysql防止SQL注入的方法小结
2019/04/27 PHP
Nigma vs AM BO3 第一场2.13
2021/03/10 DOTA
键盘 keycode的值 javascript时触发事件时很有用的要素
2009/11/02 Javascript
jquery模拟按下回车实现代码
2011/09/20 Javascript
JS实现点击下载的小例子
2013/07/10 Javascript
jQuery中animate动画第二次点击事件没反应
2015/05/07 Javascript
浅谈Javascript中substr和substring的区别
2015/09/30 Javascript
js判断复选框是否选中及选中个数的实现代码
2016/05/30 Javascript
AngularJS入门教程之更多模板详解
2016/08/19 Javascript
JavaScript定义全局对象的方法示例
2017/01/12 Javascript
js实现简单的手风琴效果
2017/02/27 Javascript
JS实现批量上传文件并显示进度功能
2017/06/27 Javascript
animate.css在vue项目中的使用教程
2018/08/05 Javascript
浅谈vue同一页面中拥有两个表单时,的验证问题
2018/09/18 Javascript
Vue+Webpack完美整合富文本编辑器TinyMce的方法
2018/11/30 Javascript
使用layui实现树形结构的方法
2019/09/20 Javascript
vue elementui 实现搜索栏公共组件封装的实例代码
2020/01/20 Javascript
js实现详情页放大镜效果
2020/10/28 Javascript
Python实现简单的代理服务器
2015/07/25 Python
Python实现替换文件中指定内容的方法
2018/03/19 Python
python-docx修改已存在的Word文档的表格的字体格式方法
2018/05/08 Python
基于wxPython的GUI实现输入对话框(2)
2019/02/27 Python
python的pygal模块绘制反正切函数图像方法
2019/07/16 Python
Tensorflow与Keras自适应使用显存方式
2020/06/22 Python
使用HTML5中的contentEditable来将多行文本自动增高
2016/03/01 HTML / CSS
有机童装:Toby Tiger
2018/05/23 全球购物
美国克罗格超市在线购物:Kroger
2019/06/21 全球购物
说出数据连接池的工作机制是什么?
2013/04/19 面试题
霸气队列口号
2014/06/18 职场文书
优秀毕业生的求职信
2014/07/21 职场文书
pytorch--之halfTensor的使用详解
2021/05/24 Python