zoukankan      html  css  js  c++  java
  • 闭包

    变量的作用域以及作用域链

    延长变量的作用域

    请看下面的例子

    function f1(){
            var n=a;
            function f2(){
                alert(n); // a
            }
            //f2();
        }

    上面的代码很简单,我们在f1里面去调用f2()当然可以弹出n的值a,但是如果我们在外部全局执行环境里面还要获得n的值,这又该怎么办?这就是刚刚的提问,外部的执行环境要求访问内部执行环境的值。

     从外往里访问,这里就可以通过闭包来实现这个效果,把上面的代码稍作修改:

        function f1(){
            var n=999; //私有变量
        
            //在函数f1内定义另外的函数作为f1的方法函数
            function f2(){
                alert(n); //引用外层函数f1的临时变量n
            }
            return f2; //返回内部函数
        }
        //调用函数
        var result=f1();
        result(); // 999

    当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包

    实际应用中会遇到闭包的情况

     界面上有一组a标签,分别点击,希望点击不同的a标签弹出不同的结果,代码如下:

        <ul>
            <li><a href="#">第0个链接</a></li>
            <li><a href="#">第1个链接</a></li>
            <li><a href="#">第2个链接</a></li>
            <li><a href="#">第3个链接</a></li>
        </ul>    
        
        var as = document.getElementsByTagName("a");
        for(var i=0;i<as.length;i++){
            as[i].onclick = function(){
                alert("你现在单击的是第" + i + "个链接");
            }
        }

    上面这段代码的估计大家都遇到过类似的,想要的效果和实际出现的效果不一致,本来想点击每一个,弹出不同的i的值,但是没想到最后弹出的i的值都是4。
    这正是由于变量的作用域链影响造成的,因为在用户单击a标签的时候才会调用onclick指向的匿名函数。而调用时,需要得到变量i的值,js解析程序首先会在匿名函数内部查找i,但是没有定义。于是往外找,在外部执行环境中找到变量i,但是这个i已经被循环到4了,因为for循环在页面初始化的时候已经被执行了。所以匿名函数里面的i实际上取得的是外部作用域链中i的值。想要改正这个错误,其实就是把i的值传入到匿名函数值就行了。但是匿名函数又不能传值。这个时候,我们就可以用闭包。
    先创建这样一个函数:

        function closureTest(num){
            return function(){
                alert("你现在单击的是第" + num + "个链接")
            }
        }

    这个函数直接返回了一个匿名函数,之前讲过闭包,所以,当返回的这个函数在外部被接收的时候,__外层函数closureTest里的变量num,就会被保存起来__,所以,将之前循环的代码修改一下:

        for(var i=0;i<as.length;i++){
            as[i].onclick = closureTest(i);
        }

    循环里面onclick调用的函数closureTest,并传入了参数i,而closureTest返回了匿名函数,所以根据闭包的原理,传入的参数i,就被保存在了内存当中,外部访问的就是每次不一样的值了。当然,你也可以直接写成下面这个样子:

        for(var i=0;i<as.length;i++){
            as[i].onclick = (function(i){
                return function(){
                    alert("你现在单击的是第" + i + "个链接")
                }
            })(i);
        }

  • 相关阅读:
    数据类型装换
    变量及数据类型
    27 网络通信协议 udp tcp
    26 socket简单操作
    26 socket简单操作
    14 内置函数 递归 二分法查找
    15 装饰器 开闭原则 代参装饰器 多个装饰器同一函数应用
    12 生成器和生成器函数以及各种推导式
    13 内置函数 匿名函数 eval,exec,compile
    10 函数进阶 动态传参 作用域和名称空间 函数的嵌套 全局变量
  • 原文地址:https://www.cnblogs.com/huzhen/p/4095366.html
Copyright © 2011-2022 走看看