• 浅谈JavaScript的函数表达式(闭包)


      前文已经简单的介绍了函数的闭包。函数的闭包就是有权访问另一个函数作用域的函数,也就是函数内部又定义了一个函数。

    1 var Super=function(num){
    2                         var count=num;
    3                         return function(){
    4                             console.log(count);
    5                         }
    6                     }
    7                     var result=Super(3);//此时result是一个函数
    8                     result();//输出3

      上面的代码定义了一个函数Super,同时在Super函数内部又定义了一个匿名函数作为返回值。第七行调用Super函数,此时result是一个函数。第8行执行了result函数,输出为3。这就是闭包的体现,因为上面的Super函数已经执行结束,但是它的内部变量count的值依然没有被释放,count的还在被匿名函数引用,所以没有办法释放。如果要释放count,我们需要 result=null ,将null赋值给result。

      在前文已经介绍了函数的作用域链,当函数第一次被调用时会创建一个作用域链,并作用域链赋值给一个特殊的内部属性。在作用域链中,函数的外部函数的活动对象位于第二位,外部函数的外部函数的活动对象位于第三位,以此类推,全局变量的作用域链位于最底部。

     1 var count=2;
     2 console.log(count);//2
     3 count=3;
     4 console.log(count);//3
     5 var Super=function(num){
     6 var count=num;//作用域链第二位
     7 console.log(count);//1
     8 return function(){
     9 var count=5;//作用域链第一位
    10 console.log(count);
    11 }
    12 }
    13 var result= new Super(1);
    14 result();//输出5

      上面的代码中,能够清晰地了解到变量的作用域。闭包函数的内部变量位于最顶端,全局变量位于最底部。

      在闭包中使用this对象也可能会导致一些问题,this对象是在函数运行时,基于函数的执行环境绑定的。在全局函数中,this指向window对象。而函数作为某个对象的方式调用时,this等于那个对象。不过匿名函数的执行环境具有全局性,因此this指向window

     1 var obj={
     2                         name:"heh",
     3                         getName:function(){
     4                             var that=this;
     5                             return function(){
     6                                 return that.name;
     7                             }
     8                         }
     9                     };
    10                     var one=obj.getName();
    11                     var name=one();//heh

      上面的代码中,通过字面量的方式创建了对象obj,定义了对象的属性name和方法getName。但是在getName内部,我们定义了闭包函数。如果想在闭包函数中访问name,通过this是访问不到的。所以需要在闭包函数的外部定义一个变量that,指向this。在getName中定义的变量,在闭包函数中仍然可以继续使用。

      JavaScript中没有块级作用域的概念,这意味着块级中定义的变量,实际在函数内部都是可以使用的。

    1 for(var i=0;i<10;i++){
    2                         console.log(i);
    3                     }
    4                     console.log(i);//输出10

      上面的代码中,我们在for循环中定义了变量i,但是我们在for循环外部依然可以使用i。for循环结束后,i变量并没有被销毁。

      JavaScript可以使用匿名函数来模仿块级作用域,从而避免该类问题的发生。

      

    1 (function(){
    2                         for(var i=0;i<10;i++){
    3                             console.log(i);
    4                         }
    5                     })();
    6                     console.log(i);

      上面的代码中,我们将块级作用域放在了一个匿名函数中,同时将匿名函数放在一对括号中,这表示一个函数表达式。在函数表达式外部的括号,表示立即调用该函数。在第六行调用该函数的时候,会发生报错,因为i并没有定义。

      

    1 var testFunc=function(){
    2                         for(var i=0;i<10;i++){
    3                             console.log(i);
    4                         }
    5                     };
    6                     testFunc();
    7                     console.log(i);

      这个代码,和我们上面的代码是一样的,都是通过函数表达式来定义函数。

      

    1 function(){
    2                         for(var i=0;i<10;i++){
    3                             console.log(i);
    4                         }
    5                     }();

      上面的代码是错误的。我们知道函数的定义方法,可以通过function和函数表达式。通过function声明函数的时候,function后面不能跟圆括号。函数表达式的后面可以跟圆括号。

      

    1 var testFunc=function(){
    2                         for(var i=0;i<10;i++){
    3                             console.log(i);
    4                         }
    5                     }();

      一般来说在开发过程中,应该尽量少向全局对象中添加函数和变量。太多的全局函数和变量容易导致命名的冲突以及内存的泄露。我们可以在块级函数中完成所有的操作。

      

    1 (function(){
    2                         var now = new Date();
    3                         console.log(now.getFullYear()+"-"+(now.getMonth()+1)+"-"+now.getDate()+" "+now.getHours()+":"+now.getMinutes()+":"+now.getSeconds());
    4                     })();

      通过上面的代码,我们能够当前的日期和时间。

       

  • 相关阅读:
    JavaSE-集合的遍历
    JavaSE-Collection常用方法
    JavaSE-异常
    JavaSE-匿名类_匿名内部类的使用
    JavaSE-内部类
    JavaSE-接口应用举例
    java线程的使用(Runnable)
    list根据所存对象属性排序
    Unable to locate appropriate constructor on class异常
    redis在java项目中的使用
  • 原文地址:https://www.cnblogs.com/ggz19/p/8435546.html
Copyright © 2020-2023  润新知