初步学习javascript匿名函数笔记

本节内容包括如下几点:

1、函数的声明和函数表达式的区别

2、什么是匿名函数

3、什么是闭包

4、关于在匿名函数中用this引发的问题

5、关于模仿块级作用域



函数的声明如下

function name(arg1,arg2){
  //函数体
}

也可以以函数表达式的形式定义函数、如下:

var name=function(arg1,arg2){
  //函数体
}

函数声明和函数表达式之间的主要区别:

1、函数声明会在代码执行之前被加载到作用域中,而函数表达式则是在代码执行到那一行的时候才会有定义。

2、函数的声明会给函数指定一个名字,而函数表达式则是创建一个匿名函数。


所以所谓匿名函数,就是没有名字的函数,有时候也称拉 姆达(lambda)函数。

例如:

 function createComparisonFunction(propertyName){
         return function(object1,object2){
            var value1=object1[propertyName];
            var value2=object2[propertyName];
            if(value1 < value2){
              return -1;
            }else if(value1 > value2){
              return 1;
            }else{
              return 0;
            }
         }
      }
createComparisonFunction()就返回了一个匿名函数,返回的函数赋值给了一个变量。

闭包:是指有权访问另一个函数作用域中的变量的函数、闭包会引用包含函数的整个活动对象

例如上个实例蓝色文字标注的那两行代码是内部函数(一个匿名函数)中的代码,它们访问了外部函数中的变量propertyName,闭包所保存的是整个变量对象。

但是闭包有一个特点:只能取得包含函数中任何变量的最后一个值。

例如:

     function createFunctions(){
        var result=new Array();
        for(var i=0;i<10;i++){
           result[i]=function(){
             return i;
           };    //返回的始终会是10,因为闭包只能取得包含函数中任何变量的最后一个值。
        }
        return result;
     }
     
     var funs=createFunctions();
     for(var i=0;i<funs.length;i++){
        document.write(funs[i]()+"<br/>");
     }
这个函数会返回一个数组,而且数组中的每个值都是10,如果要得到预期的结果即0、1、2......  可以做如下变化

function createFunctions(){
        var result=new Array();
           result[i]=function(num){
              return function(){
                  return num;
              }
           }(i);
        }
        return result;
     }
     
     var funs=createFunctions();
     for(var i=0;i<funs.length;i++){
        document.write(funs[i]()+"<br/>");
     }

由于函数参数按值传递,所以会将变量i的当前值传递给参数num、而在这个匿名函数内部,又创建并返回了一个访问num的闭包。

灰色背景的代码页可以用如下代码替换:

 result[i]=function(){
             return i;
           }(i);

关于this对象

在闭包中使用this对象会导致的一些问题、这是因为、匿名函数的执行环境具有全局性,因此其this对象通常指向window、举例如下:

  var name="the window";
     var object={
       name:"this object",
       getNameFunc:function(){
           return function(){
              return this.name;
           };
       }
     };
     alert(object.getNameFunc()());//the window
结果返回the window、为什么匿名函数没有取得其包含作用域(或外部作用域)的this对象了?

因为每个函数在被调用时,它的活动对象会自动取得this和arguments这两个特殊的变量。内部函数在搜索这两个变量时,只会搜索到它的活动对象为止。

如果把外部作用域中的this对象保存在一个闭包能够访问到的变量里、就可以让闭包访问该对象。修改如下:

var name="the window";
     var object={
       name:"this object",
       getNameFunc:function(){
           var that=this;
           return function(){
             return that.name;
           };
       }
     };
     alert(object.getNameFunc()());//this object

this和arguments也存在同样的问题,如果想访问作用域中的arguments对象,必须将该对象的引用保存到另一个闭包能够访问的变量中。

 

关于内存泄露

如果闭包的作用域链中保存着一个html元素,则意味着该元素无法被销毁;例如:

function demoHandler(){
   var element=document.getElementId("something");
    element.οnclick=function(){
    alert(element.id);
  };
}
由于匿名函数中保存了一个对demoHandler()的活动对象的引用,因此只要匿名函数存在、element的引用数就大于等于1,因此它所占用的内存就永远不会回收。

可以进行如下优化:

function demoHandler(){
   var element=document.getElementId("something");
    var id=element.id;
    element.οnclick=function(){
    alert(id);
  };
    element=null;
 }

关于模仿块级作用域

javascript没有块级作用域的概念,即在块级语句中定义的变量,实际上是在包含该语句的函数中创建的、例如:

function writeNumbers(count){
   for(var i=0;i<count;i++){
     alert(i);
  }
   alert(i);//count 即在块级语句之外也能够访问i
}

匿名函数可以用来模仿块级作用域

块级作用域(私有作用域)的匿名函数语法如下:

(function(){

 //这里是块级作用域

})();

此段代码表示定义并立即调用了一个匿名函数。(最后面的那一对圆括号代表立即调用这个函数)

此语法可以用以下这种方式理解:

例如调用writeNumbers()函数的方式

可以是 var count=5; writeNumbers(count);

也可以直接 writeNumbers(5);

那么我们是不是也可以用函数的值直接来取代函数名字了?

var someFunction=function(){

  //这里是块级作用域

};

someFunction();//定义一个匿名函数并赋值给变量someFunction,然后用调用函数的方式是在函数函数名称后面添加一对圆括号,即:someFunction();

如果综合以上的例子,是不是也可以这样调用

function(){

  //这里是块级作用域

}(); //出错

这段代码会导致语法错误,是因为javascript将function关键字当做一个函数声明的开始,而函数的声明后面是不能够跟圆括号的。然而,函数表达式的后面是可以跟圆括号的。

因此,要将函数的声明转换为函数的表达式,只要在前面给它加一对圆括号即可、即变成了块级作用域的语句:

(function(){

  //这里是块级作用域

})();

例如:

function outpubNum(count){
   (function(){
     for(var i=0;i< count;i++){
       alert(i);
      }
   })();
   alert(i);//在这里调用i会导致错误
 }
这种技术可以限制向全局作用域中添加过多的变量和函数。











  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值