zoukankan      html  css  js  c++  java
  • JS核心知识点梳理——闭包

    闭包

    闭包这个东西咋说呢,不同的程序员,不同的资料都有不同的解释,你可以把它理解成一个函数,也可以把它理解函数+执行环境。

    我们这里不纠结闭包的定义,而是关注闭包的现象,应用,再结合相关面试题去攻克它,最后谈一下我对闭包的理解。

    现象

    之前说过,函数执行,生成执行环境,函数执行完,销毁执行环境。嗯,听上去很正常,不用的东西就销毁嘛。

    但是如果函数执行完,该函数上下文还用怎么办,有用的东西肯定不敢销毁了,这个就是闭包的现象,那么引起这个现象的鄙人就把它理解成闭包!

     1 function foo () {
     2     var a = 1
     3     return function bar () {
     4         a++
     5         console.log(a)
     6     }
     7 }
     8 var b = foo() //函数执行完,我就问你foo的上下文你敢销毁吗?
     9 b()  //  2
    10 b()  //  3

    大家看到foo执行完的结果赋值给了b,也就是函数bar赋值给了b,未来我可能让b执行,也就是让bar执行,所以我需要保证让bar能访问上下文不被销毁。bar能访问的上下文实际上是foo执行的上下文。所以foo执行完以后的上下文不会被销毁,会继续存在。

    我的理解是 函数向外层作用域暴露出来一个内部引用,那么就存在闭包现象。(真的没有必要纠结闭包到底是啥,是函数?内部整体?)

    应用

    以下代码的功能是要实现为5个input按钮循环绑定click点击事件,绑定完成后点击1、2、3、4、5五个按钮分别会alert输出0、1、2、3、4五个字符。(腾讯)

    请问如下代码是否能实现?

    如果不能实现那么现在的效果是什么样的?

    应该做怎样的修改才能达到我们想要的效果,并说明原理?

     1 <div id="btnBox">
     2     <input type="button" value="button_1" />
     3     <input type="button" value="button_2" />
     4     <input type="button" value="button_3" />
     5     <input type="button" value="button_4" />
     6     <input type="button" value="button_5" />
     7 </div>
     8 <script type="text/javascript">
     9     var btnBox=document.getElementById('btnBox'),
    10     inputs=btnBox.getElementsByTagName('input');
    11     var l=inputs.length;
    12     for(var i=0;i<l;i++){
    13         inputs[i].onclick=function(){
    14             alert(i);
    15         }
    16     }
    17 </script>

    解决思路1:没有块作用域,我就用es6的let形成块作用域

    1 for(let i=0;i<l;i++){
    2      inputs[i].onclick=function(){
    3              alert(i);
    4      }
    5 }

    解决思路2:每次绑定的时候i其实都是正确的,我能不能用另外一个变量将每次的i存起来呢?

    1 //这样行吗?
    2 for(var i=0;i<l;i++){
    3         inputs[i].onclick=function(){
    4             var num = i  
    5             alert(num);
    6         }
    7     }
    8 //这样还是不行,因为回调函数定义的时候并不会执行,所以当var num = i  执行的时候i已经等于5了

    那么我就让回调函数定义的时候里面的代码能立即执行,接收到参数0,1,2,3,4

    1 for(var i=0;i<l;i++){
    2         inputs[i].onclick=(function(){
    3             var num = i  
    4             alert(num);
    5         })(i)
    6     }
    7 //这样也有问题i传递进去了,但是里面核心代码定义也执行了,我想让它点击的时候再执行
    1 for(var i=0;i<l;i++){
    2         inputs[i].onclick=(function(){
    3             var num = i
    4             return function (e) { //注意这个时候e是啥,是点击的事件
    5                 console.log(num)
    6             }
    7         })(i)
    8     } //这样就没毛病了,返回一个方法,不会立即执行,i传进去了,给了num,由于有闭包,又不会被销毁,完美
  • 相关阅读:
    Android 之流媒体播放器,广播侧下方这么简单。
    POJ 1146:ID Codes
    NYOJ 47 河问题
    浏览器 HTTP 协议缓存机制详解--网络缓存决策机制流程图
    写给后端程序员的HTTP缓存原理介绍--怎样决定一个资源的Cache-Control策略呢
    浅谈Web缓存-缓存的实现过程详解
    国内各大互联网公司相关技术博客3.0版 (集合腾讯、阿里、百度、搜狐、新浪、网易、360等共29个)
    知名技术团队博客
    【Web缓存机制系列】2 – Web浏览器的缓存机制-(新鲜度 校验值)
    学习是一件艰苦的事情
  • 原文地址:https://www.cnblogs.com/benmumu/p/11208048.html
Copyright © 2011-2022 走看看