zoukankan      html  css  js  c++  java
  • js 闭包 理解

    1.什么是闭包

    定义:是指有权访问另一个函数作用域中的变量的函数

    创建闭包:在一个函数内部创建另一个函数

    基本特点 在返回的匿名函数中 可以调用外部函数的变量 如下例中所示 内部函数(匿名函数) 可以访问外部函数的变量num 形式如a[num] 原因是匿名函数作用域链中包括外部函数test1的作用域

    闭包有权访问包含函数内部的所有变量 如下面的 外部函数定义变量d 在闭包中可以直接访问到d (var dd=d)

     function test1(num){
             var d;
    
            return function(a,b){
                var d1=a[num],d2=b[num];
               var dd=d;
      }
    
        }
    

      

    实例参考 此时点击产品1 到 产品4 结果都是5 点击匿名函数的作用域链中包括外部函数init的活动对象 都是引用的同一个变量i 都是5 。解决办法 返回的匿名函数 通过立即执行函数 把参数i传给匿名函数

    <!DOCTYPE HTML>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>闭包演示</title>
        <style type="text/css">
            p {background:gold;}
        </style>
        <script type="text/javascript">
            function init() {
                var pAry = document.getElementsByTagName("p");
                for( var i=0; i<pAry.length; i++ ) {
                    pAry[i].onclick = function() {
                        alert(i);
                    }
                }
            }
         
        </script>
    </head>
    <body onload="init();">
    <p>产品 0</p>
    <p>产品 1</p>
    <p>产品 2</p>
    <p>产品 3</p>
    <p>产品 4</p>
    </body>
    </html>
    

     弹出结果都是5截图 

    解决办法:立即执行匿名函数 参数i是循环i的值 传递给num形参 匿名函数里 在创建闭包 可以访问这个传递过来的值num 

    pAry[i].onclick = function(num){//......}(i)

      

    <!DOCTYPE HTML>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>闭包演示</title>
        <style type="text/css">
            p {background:gold;}
        </style>
        <script type="text/javascript">
              /*修改后*/
              function init() {
             var pAry = document.getElementsByTagName("p");
             for( var i=0; i<pAry.length; i++ ) {
             pAry[i].onclick = function(num) {
    
             return function(){
             alert(num)
             }
             }(i)
             }
             }
    
        </script>
    </head>
    <body onload="init();">
    <p>产品 0</p>
    <p>产品 1</p>
    <p>产品 2</p>
    <p>产品 3</p>
    <p>产品 4</p>
    </body>
    </html>
    

      结果点击第一展示

    还有这样写也是可以的

      function a(){
                var pAry = document.getElementsByTagName("p");
                for( var i=0; i<pAry.length; i++ ) {
                    (function(num){
                        pAry[num].onclick = function() {
                            alert(num);
                        }
                    })(i)
                }
            }
    

      

    1.1 闭包的原理

    -1) 闭包的作用域链 包括 闭包自身的作用域(一般返回匿名函数的作用域),外部函数的作用域(包含的外部函数),全局作用域

    -2)通常,函数的作用域和所有变量都会在函数执行结束后被销毁

    -3)函数返回一个闭包,这个函数的作用域会一直保存在内存中直到闭包不存在为止

    使用闭包可以模仿块级作用域

    -1)创建闭包并立即执行这个函数 不会再内存中留下该函数的引用

    -2 )结果 函数内部的所有变量都会被立即销毁

    2.什么是作用域链


    执行环境:定义了变量或函数有权访问其他数据,决定它们各自的行为。

    变量对象:每个执行环境都有一个与之关联的变量对象。

    执行环境定义的所有变量和函数都保存在变量对象中。编写代码无法访问这个对象,解析器在处理数据时会在后台使用它。

    -1)全局执行环境是最外围的一个执行环境

    -2)web浏览器中,全局执行环境默认是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的

    -3)某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义都随之销毁  全局执行环境直到应用程序退出--例如关闭网页或浏览器时才会被销毁

    -4)每个函数都有自己的执行环境

    作用域链:当代码在一个执行环境中执行时,会创建变量对象 一个作用域链

    作用域链用途:保证对执行环境有权访问的所有变量和函数的有序访问

    标识符解析:沿着作用域链一级一级的向上搜索标识符的过程。

    函数参数也被当做变量来看待,因此访问规则与执行环境中的其它变量相同。 例子:下面函数chageColor(num){} 在闭包里tempColor(a){}里可用a[num]访问

    实例解析

    <script type="text/javascript">
        /*全局变量*/
        var color = 'red' ;
    
        function changeColor(num){
            var otherColor = 'blue',
                another =color,
             chage = changeColor();
    
    
                function tempColor(a){
                      var temp = otherColor,
                          temp2 = color,
                          temp3 = changeColor();/*这里可以访问上层执行环境otherColor another chage 和全局color*/
                      var u =a[num];
    
    
                }
    
        }
    </script>
    

      

      

      

      全局 window

                 |

                 |-------------color 全局变量

                 |------------changeColor()

                                                 |

                                                 |---------------otherColor(局部变量 还有两个就是调用的上层全局环境里的color变量和函数chageColor)

                                                 |---------------tempColor()

                                                                                   |-------------------h(变量h不能被上层执行环境调用 只能在tempColor()里调用 标识符向上搜索沿着作用域链 这个环境里可以调用外层环境和全局环境的变量)

    参考:

    http://www.cnblogs.com/yugege/p/6526215.html 闭包

    ECMAScript 闭包(closure)

  • 相关阅读:
    PHPstorm配置xdebug问题小记
    PHP 实现遍历出目录及其子文件
    localStorage存、取数组
    关于用户体验
    PHP实现导出Excel文件
    js将一位数组分割成每三个一组
    vue 动态绑定背景图片
    父组件传值给子组件
    数组字符串 转化成 对象
    Vuex 页面刷新后store保存的数据会丢失 取cookie值
  • 原文地址:https://www.cnblogs.com/xxx91hx/p/4604024.html
Copyright © 2011-2022 走看看