Javascript 匿名函数与闭包

Javascript 匿名函数与闭包

一、函数的几种定义

1、函数关键字(function)语句
      function func1(){
          alert("func1");
      }
      func1();
2、函数直接量(Function Literals)
      var func2 = function(){
          alert("func2");
      }
      func2();
虽然函数直接量创建的是未命名函数,但是它的语法也规定它可以指定函数名。
      var func4 = function func5(){
          alert("func5");
      }
      func4();
函数直接量在编写调用自身的递归函数时非常有用。如:
      var func6 = function fact(x) {
          if (x <= 1 ) {
              return 1 ;
          }  else   {
              return  x * fact(x - 1 );
          }
      };
      alert(func6(4));
上面的代码定义了一个未命名函数,并对它的引用存储在变量func6中。它并没有真正的创建一个名为fact()的函数,只是允许函数体用这个名字来引用自身。

但是要注意,JavaScript1.5之前的版本中没有正确实现这种命名的函数直接量。

3、使用Function对象构造函数
      var func3 = new Function('x','y','var r = x + y;alert(r);');
      func3(3,4);
Functino()构造函数可以接受任意多个字符串参数。它的最后一个参数是函数的主体,其中可以包含任何JavaScript语句,语句之 间用分号分隔。其他的参数

都是用来说明函数要定义的形式参数名的字符串。如果你定义的函数没有参数,那么可以只需给构造函数传递一个函数的主体字符串即可。

无论你用上述哪种方式去定义函数,JS解释器都会把它翻译成一个Function对象。这一点我们可以通过调用函数对象的constructor属性,进行验证。
      alert(func1.constructor);
      alert(func2.constructor);
      alert(func3.constructor);
结果如下:
function Function() {
    [native code]
}

二、匿名函数

什么是匿名函数
顾名思义,匿名函数就是没有实际名字的函数。从这个层面上来看,上述方式2和方式3什么时都没有指定函数的名字。都属于匿名函数。
方式2函数直接量创建的是未命名函数,而且不会自动地将这个函数存储在属性中。但是,比起Function() 构造函数来说,函数直接量有一个重要的优点。由

Function()构造函数创建的函数的主体必须用一个字符串说明,用这种方式来表达一个长而复杂的函数 是狠笨拙的。但是函数直接量的主体使用的却是标准的

JavaScript语法。而且函数直接量只被解析一次,而作为字符串传递给Function()构造 函数的JavaScript代码则在每次调用构造函数时只需被解析一次和编译一次。

匿名函数的调用

要调用一个函数,我们必须要有方法定位它,引用它。
1)将函数赋值给某一变量对它进行引用;
var abc=function(x,y){  
    return x+y;  
}  
alert(abc(2,3)); // "5"


2)使用()将匿名函数括起来,然后后面再加一对小括号(包含参数列表)
(function($) {
    //jQuery 代码实现部分
})(jQuery);
这是我们在jQuery中看到的代码片段。
小括号能把我们的表达式组合分块,并且每一块,也就是每一对小括号,都有一个返回值。这个返回值实际上也就是小括号中表达式的返回值。所以,当我们用一对小括号把匿名函数括起来的时候,实际上小括号对返回的,就是一个匿名函数的Function对象。因此,小括号对加上匿名函数就如同有名字的函数般被我们取得它的引用位置了。所以如果在这个引用变量后面再加上参数列表,就会实现普通函数的调用形式。


3)优先表达式:由于Javascript执行表达式是从圆括号里面到外面,所以可以用圆括号强制执行声明的函数。
( function(){
alert(2);
} ( ) );


4)Void操作符:用void操作符执行一个没有用圆括号包围的一个单独操作数。
void function(){
alert(3);
}();

5) eval函数动态执行。
    eval(function(){
          alert(4);
      }());

为什么要用匿名函数
“全局变量是魔鬼”。配合var关键字,匿名函数可以有效的保证在页面上写入Javascript,而不会造成全局变量的污染。这在给一个不是很熟悉的页面增加Javascript时非常有效,也很优美。当然对于我个人而言,还是习惯采用面向对象的思想去避免变量重复,增强代码可读性。

三、闭包

闭包,其实是一种语言特性,它是指的是程序设计语言中,允许将函数看作对象,然后能像在对象中的操作搬在函数中定义实例(局部)变量,而这些变量能在函数中保存到函数的实例对象销毁为止,其它代码块能通过某种方式获取这些实例(局部)变量的值并进行应用扩展。是否应用了闭包特性,必须确定该段代码有没有最重要的要素:未销毁的局部变量。那么很显然,没有任何实现的匿名函数不可能应用了闭包特性。但如果匿名函数 里面有实现呢?那也还得确定它的实现中有没有用到那些未销毁的局部变量。

简而言之,闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。例如:
function closure(){
    var x = 10;
    setTimeout(
        function(){ alert( x ); } //匿名函数
    , 1000);
}
closure ();
在该示例中closure函数瞬间执行完毕,正常情况下x变量应该得到释放。但由于内嵌的匿名函数中有对x变量的引用。所以必须等1000ms后匿名函数执行完毕后,x变量所占用的资源才得到释放。

闭包应用
function doAdd( x, y){
    alert( x + y );
}
function doSetTimeout( x , y  , time ){
    setTimeout(doAdd (' +  x + ',' +  y + ')' , time );    
}

上面的doSetTimeouty函数十分难以阅读,也不容易编写,但如果使用闭包就可以让代码更加清晰。

function doSetTimeout ( x , y , time ){
    setTimeout(
        function(){
            doAdd( x , y )
        }          
    , time );   
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
匿名函数,也称为拉姆达函数,是一种使用JavaScript函数的强大方式。以下总结了匿名函数的特点: 任何函数表达式从技术上说都是匿名函数,因为没有引用它们的确定的方式; 在无法确定如何引用函数的情况下,递归函数就会变得比较复杂; 递归函数应该始终使用arguments.callee来递归地调用自身,不要使用函数名--函数名可能会发生变化。 当在函数内部定义了其他函数时,就创建了闭包闭包有权访问包含函数内部的所有变量,原理如下: 在后台执行环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域; 通常,函数的作用域及其所有变量都会在函数执行结束后被销毁; 但是,当函数返回了一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止;使用闭包可以在JavaScript中模仿块级作用域(JavaScript本身没有块级作用域的概念),要点如下: 创建并立即调用一个函数,这样既可以执行其中的代码,又不会在内存中留下对该函数的引用; 结果就是函数内部的所有变量都会被立即销毁--除非将某些变量赋值给了包含作用域(即外部作用域)中的变量。 闭包还可以用于在对象中创建私有变量,相关概念和要点如下: 即使JavaScript中没有正式的私有对象属性的概念,但可以使用闭包来实现公有方法,而通过公有方法可以访问在包含作用域中定义的变量; 有权访问私有变量的公有方法叫做特权方法; 可以使用构造函数模式、原型模式来实现自定义类型的特权方法,也可以使用模块模式、增强的模块模式来实现单例的特权方法。 JavaScript中的匿名函数闭包都是非常有用的特性,利用它们可以实现很多功能。不过,因为创建闭包必须维护额外的作用域,所以过度使用它们可能会占用大量内存。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春哥一号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值