javaScript闭包

来源:互联网 发布:足彩过滤软件 编辑:程序博客网 时间:2024/06/01 11:46

 

一、介绍:

包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

 

二、 理解闭包就必须要理解js函数中的变量作用域

  变量的作用域无非就是两种:全局变量和局部变量

  Javascript语言的特殊之处,就在于函数内部可以直接读取全局变

    <script>

         Var n=999;

          Function  fun1(){

             Alert(n);

           } 

            Fun1(); //输出 999

           Function  fun2(){

                Var nn=999;

             }

             Fun2(); 

             Alert (nn); //不能输出

这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!

            Function fun3(){

                Mm=999;

         } 

            Fun3();

           Alert(mm);  //输出 999

三、闭包的概念

     如何在函数的外部读取数据呢?

  各种专业文献上的"闭包"closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"

 所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

     <script>

          Function  fun1(){

               Var  a=999;

                 Function fun2(){

                    Alert(n);

                }

                 Return fun2;

           }

          Var  func=fun1();

               Func(); //输出 999

        //func实际上是 闭包 fun2函数

                

函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。

 这也是javaScript 语言的特性"链式作用域"结构子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

 

四、闭包的用途

  闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

 如何理解“变量的值始终保持在内存中

    <script> 

        Function fun1(){

           Var  n=1;

             Nadd=function(){   注意这里 nadd 前面没有加 var

                  N+=1;  // 所以这里是全局变量,Nadd=function() 是一个匿名函数,匿名函数本身也是一个闭包在函数外部对函数内部的局部变量进行操作。

               }

              Function fun2(){

                     Alert(n);

                 }

                    Return  fun2;

  }

 

 Var  result=fun1(); //执行fun1() 方法

        Result() ;// 实际上是执行 fun2(),也就是说把 fun2() 赋给了 result() 方法  输出: 1这里没有自加 

         //再来执行 自加方法

          Nadd();  自加了  现在就是 2

          Result() ;  输出2

 result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

  什么会这样呢?原因就在于f1f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

五、使用闭包的注意点

  1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

 

六、 理解下面代码,你就完全理解闭包了。

     var name = "The Window";

var object = {  //类的内部封装

    name : "My Object",

    getNameFunc : function(){

        return function(){

            return this.name;

        };

    }

};

    alert(object.getNameFunc()());   输出结果 the  windows

由于  the windows 是全局变量   my object 是类中属性(局部变量)

 而我们访问的是他的方法 所以最后的结果是 the windows

-------------------------- 

 var name="the windw"; 全局变量

    var object ={  函数体

        name : "My Object",  全局变量

        getNameFunc : function(){  闭包函数

            var that = this;  将内部对象赋给 内部变量

//也就是说that拥有了当前对象的所有属性和方法 所以结果是 my object

            return function(){

                 return that.name;  返回内部变量值

            };   函数套函数 

         }

    };

    alert(object.getNameFunc()()); 输出 my object

 

 

0 0
原创粉丝点击