码迷,mamicode.com
首页 > 编程语言 > 详细

浅谈javascript中的闭包

时间:2015-09-25 21:47:41      阅读:287      评论:0      收藏:0      [点我收藏+]

标签:

引入定义:闭包只有权访问另一个函数中的作用域中的函数。

简单点说,就是当某函数a执行完毕后,闭包不会使得GC(JavaScript的回收机制)去回收a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。

代码示例:

window.onload = function(){
        function createComparisonFunction(propertyName){
            return function(object1, object2){
                var value1 = object1[propertyName];
                var value2 = object2[propertyName];
                console.log(arguments);
                if(value1 < value2){
                    return –1;
                }else if(value1 > value2){
                    return 1;
                }else{
                    return 0;
                }
            };
        }
        var compareNames = createComparisonFunction("name");
        var result = compareNames({name:"Nicholas"},{name:"Greg"});

在此例中,当调用玩createComparisonFunction函数后,局部活动对象,即

调用createComparisonFunction这个函数是产生的活动对象理应被销毁,但是如我们在下面调用的语句,compareNames依然成功调用,而注意到,我们在匿名函数内(3行)是引用了createComparisonFunction的西参数的,其实这就是闭包的一个细微体现吧。
不信,咱再证明一下无妨:在上面代码的第五行,不是有一个控制带输出语句吗,其打印的是匿名函数的匿名参数arguments,结果附上:
技术分享

从上图中,我们不难看出,在匿名函数的<function scop>中,保存有作用域链,其中就有createComparisonFunction的形式参数propertyName:“name”。

 

闭包注意事项1: 闭包与变量:

  在闭包中的变量有其特殊性,但其实深究一下,也其实挺普遍的:

上代码:

function createFunctions(){
            var result = new Array();
            for(var i = 0; i < 10; i++){
                result[i] = function(){
                    return i;
                };
            }
            return result;
        }
        var results = createFunctions();
        for(var i = 0; i < 10; i++){
            alert(results[i]());
        }

最终输出结果:  每一次输出都为10

解释:而当createFunction()函数返回后,变量i的值是10,此时每一个函数都引用着保存变量i的同一个变量对象,所以……

当然,我们可以通过一个非常巧妙的方法来解决这个问题:

function createFunctions(){
            var result = new Array();
            for(var i = 0; i < 10; i++){
                result[i] = function(num){   //用num来保存i的初始值
                    return function(){
                        return num;
                    }
                }(i);
            }
            return result;
        }
        var results = createFunctions();
        for(var i = 0; i < 10; i++){
            console.log(results[i]());   //0,1,2,3,4,5,6,7,8,9
        }

方法之妙,不言而喻,也许这就是语言之妙吧。

说完闭包,我们再来谈谈与其密切相关的东西,作用域链和活动对象:

    官方:  当某个函数被调用时,会创建一个执行环境及相应的作用域链,然后,使用arguments和其它命令参数的值来初始化函数的活动对象,但在作用域中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象始终处于第三位,知道作用域终点的全局执行环境。

嘛意思呢:哥总结为下:

                   1:函数一创建,即产生作用域链。

                     2:作用域链保存在arguments或其他参数中(见本文上面的截图)。

                     3:何为作用于链:

引入作用域:任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。

作用域链:即为作用域的集合。其本质上是一个指向变量对象的指针列表,它只引用但不包含变量对象。

上代码:   test1

var name = "The Window";
    var num = 100;   //   全局变量对象
    var object = {
        name: "Ny Object",
        //活动对象开始-------本地活动对象------------------
        getNameFunc: function(num){
            return function(){
                return num;
            };
        }
//        活动对象结束:------------------------------------------------------------------------
    };
    console.log(object.getNameFunc(500)());    //500

test2

var name = "The Window";
    var num = 100;   //   全局变量对象
    var object = {
        name: "Ny Object",
        //活动对象开始-------本地活动对象-------------------------------------------------
        getNameFunc: function(num){
            return function(num){
                return num;
            };
        }
//        活动对象结束:------------------------------------------------------------------------
    };
    console.log(object.getNameFunc(500)(50));    //50

test3:

var name = "The Window";
    var num = 100;   //   全局变量对象
    var object = {
        name: "Ny Object",
        //活动对象开始-------本地活动对象-------------------------------------------------
        getNameFunc: function(){
            return function(){
                return num;
            };
        }
//        活动对象结束:------------------------------------------------------------------------
    };
     console.log(object.getNameFunc()());   //100

从上面三个代码的测试结果不难看出,本地活动对象优先,然后一级一级的网上寻找目标变量(当函数要访问某个变量时)。

      其完整的寻找路径(最长的时候)即为一个作用域链。

浅谈javascript中的闭包

标签:

原文地址:http://www.cnblogs.com/Frank-C/p/4839506.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!