• Javascript 闭包与变量


    1.闭包与变量

     JavaScript中的作用域链的机制引出了一个副作用,即闭包只能取得包含函数中任何变量的最后一个值。闭包所保存的是整个变量对象,而不是某个特殊的值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function createFunctions(){ 
        var result=new Array(); 
            
        for (var i=0;i<10;i++){ 
            result[i]=function(){ 
                return i; 
            }; 
        
        return result; 
    var funcs = createFunctions(); 
    for (var i=0; i < funcs.length; i++){ 
        document.write(funcs[i]() + "<br />"); 
    }

    createFunction()函数返回一个数组。表面上看,似乎每个函数都应该返回自己的索引值,但事实并非如此,事实上每个函数的返回值都是10.因为每个函数的作用域链中都包含着createFunctions()函数的活动对象,所以它们引用的都是同一个变量i。当createFunctions()函数返回后,变量i的值就是10,此时每个函数都引用着保存变量i的同一个变量对象,所以每个函数返回后都是10.

    当然我们可以使用匿名函数强制使闭包的行为符合预期。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function createFunctions(){  
        var result=new Array();  
              
        for (var i=0;i<10;i++){  
            result[i]=function(num){
                return function(){  
                return num;  
            };  
            }(i);
        }  
        return result;  
    }  
    var funcs = createFunctions();  
    for (var i=0; i < funcs.length; i++){  
        document.write(funcs[i]() + "<br />");  
    }

    在重写了前面的createFunctions()函数后,每个函数就好返回各自不同的索引值了。在这里,我们没有直接把闭包赋值给数值,而是定义了一个匿名函数,并将立即执行该函数的结果赋值给数组。这里的匿名函数有一个参数num,也就是最终的函数要返回的值。在调用每个匿名函数时,我们传入了变量i。由于函数参数按值传递的,所以就会将变量i的当前值复制给参数num。而在这个匿名函数内部,有创建并返回了一个访问num的闭包。这样依赖,result数组中的每个函数都有自己num变量的一个副本,因此就可以返回各自不同的数值了。

    1.2关于this对象

    在闭包中使用this对象会出现一些问题,this对象是运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被当作某个对象的方法调用时,this等于那个对象。不过,匿名函数的执行环境具有全局性,因此其this对象通常指向window(当然,在通过call()和apply()改变函数执行环境时,this指向其他对象)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var name="The Window"
        
    var object={ 
        name:"My object"
        getNameFunc:function(){ 
            return function(){ 
                return this.name; 
                }; 
            
        }; 
    alert(object.getNameFunc()()); //"The Window"(在非严格模式下)

    以上代码创建了一个全局变量name,有创建了一个包含那么属性的对象,这个对象还包括一个方法——getNameFunc(),它返回一个匿名函数,而匿名函数又返回this.name.由于getNameFunc()返会一个函数。因此调用object.getNameFunc()()就会立即返回调用它的函数,结果就返回一个字符串。然而,这个例子返回的字符串是“The Window”,即全局name变量的值。

    但是,为什么匿名函数没有取得其包含作用域(或外部作用域)的this对象呢?

    每个函数在调用时,其活动对象都会自动获取两个特殊的变量:this和arguments。内部函数在搜索这两个变量时,只会搜到其活动对象为止,因此永远不肯能访问到外部函数中的这两个变量。不过,把外部作用域中的this对象保存在一个闭包能够访问的变量里,就可以放闭包访问该对象了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var name="The Window"
        
    var object={ 
        name:"My object"
        getNameFunc:function(){ 
            var that=this;
            return function(){ 
                return that.name; 
                }; 
            
        }; 
    alert(object.getNameFunc()()); //"My object"

     以上代码中,我们在定义匿名函数之前,把this对象赋值给了that变量,而在定义闭包之后,闭包也可以访问这个变量,因为它们是我们在外部函数中特意声明的一个变量。即使在函数返回之后,this也仍然引用的object,所以调用object.getName()()就返回“My object”.


      -END- 

     

  • 相关阅读:
    北漂IT男返乡2年的三线楼市观察(宜昌夷陵篇)-原创
    写一本书作者到底能拿到多少稿酬?
    书是如何定价的?
    一本书出版社拿多少,作者拿多少?书的成本几何?出版一本书出版社到底能赚多少钱?(转)
    微服务架构最强详解
    今日头条号短视频自媒体研究---最开始的短视频设备资金投入不要太大(原创)
    今日头条号短视频自媒体研究---新手上路,正确拍短视频并上传(原创)
    HTTP请求中的缓存(cache)机制
    linux kernel 中断子系统之(一)-- ARM GIC 硬件【转】
    嵌入式Linux——kmsg:分析/proc/kmsg文件以及写自己的/proc/mymsg【转】
  • 原文地址:https://www.cnblogs.com/jstarseven/p/4454527.html
Copyright © 2020-2023  润新知