匿名函数、自执行函数、闭包

1、匿名函数

匿名函数,顾名思义就是没有名字的函数。
匿名函数的调用方式:
1)创建一个匿名函数,并将匿名函数赋值给变量add,用add来进行函数的调用,调用的方式就是在变量add后面加上一对括号(),如果有参数传入的话就是add(1,2)

var add = function(x, y) {
    console.log(x+y);
}
add(1,2)   // 3

2)将匿名函数用()括起来,然后在后面加一对小括号(包含参数列表)

console.log((function(x, y){return x+y;})(1,2));   // 3
console.log((new Function('x', 'y', 'return x+y;'))(1, 2));   // 3

2、自执行函数

我们创建了一个匿名的函数,并立即执行它,由于外部无法引用它内部的变量,因此在执行完后很快就会被释放,关键是这种机制不会污染全局对象。
自执行函数,即定义和调用合为一体。

自执行函数的一些表达方式:

// 下面2个括号()都会立即执行  
(function () { /* code */ } ()); // 推荐使用这个  
(function () { /* code */ })(); // 但是这个也是可以用的

3、闭包

3.1闭包简单例子

一般情况下,函数内部可以访问函数外部的全局变量

var a = 1;//全局变量  
 function f1(){  
     alert(a);  
 }  
 f1();//1 

函数外部不能访问函数内部的局部变量

function f2(){  
    var a = 1 ; //局部变量  
}  
alert(a); //error  

有时候我们想得到函数内部的局部变量,那应该如何实现呢?这就引入了闭包的概念。

function fn1() {
    var n = 1;

    return function() {
        alert(n);
    }
}
result = fn1();
result(); //1

3.2 闭包的作用

  • 读取函数内部的变量
  • 将变量的值始终保存在内存中

一般来讲,当函数执行完毕之后,函数内部的局部活动对象就会被销毁,内存中仅保存全局作用域,即js的内存回收机制。
如果这个函数内部又嵌套了另一个函数,而这个函数是有可能在外部被调用到的.并且这个内部函数又使用了外部函数的某些变量的话.这种内存回收机制就会出现问题。如果在外部函数返回后,又直接调用了内部函数,那么内部函数就无法读取到他所需要的外部函数中变量的值了.所以js解释器在遇到函数定义的时候,会自动把函数和他可能使用的变量(包括本地变量和父级和祖先级函数的变量(自由变量))一起保存起来.也就是构建一个闭包,这些变量将不会被内存回收器所回收,只有当内部的函数不可能被调用以后(例如被删除了,或者没有了指针),才会销毁这个闭包,而没有任何一个闭包引用的变量才会被下一次内存回收启动时所回收。

3.3 自执行函数与闭包的使用
很多情况下,可以利用自执行函数和闭包来保存某个特殊状态中的值。
由于作用域链的配置机制,使得闭包只能取得包含函数中任何变量的最后一个值。即说明了闭包中所保存的是整个变量对象,而不是某一个特殊的变量。我们 用下面这个例子来说明这个问题。

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

var aa = createFunction();
alert(aa[0]()); //10
alert(aa[1]()); //10

在这个函数中,我们直接将闭包赋值给数组。这个函数会返回一个函数数组。表面上来看,似乎每个函数都应该返回自己的索引,即位置0的函数返回0,位置1的函数返回1一次类推。但实际上,如同上面例子,每个函数都返回了10。因为每个函数的作用域链中都保存createFunctions()函数的活动对象,所以它们引用的都是同一个变量i。当createFunctions()函数返回后,变量i的值死10,此时每个函数都引用着保存变量i的同一个变量对象。所以在每个函数内部i的值都是10。
所以,我们可以通过如下例子,创建一个自执行函数(匿名函数)强制让闭包的行为符合预期。

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

var bb = createFunction();
alert(aa[0]()); //0
alert(aa[1]()); //1

在这个例子中,我们没有直接将闭包赋值给数组,而是定义了一个匿名函数,并将立即执行该匿名函数的结果赋值给数组。对于立即执行的匿名函数来说,由于外部无法引用它内部的变量,因此在执行完后很快就会被释放。所以这里的匿名函数有一个参数num,也就是最终的函数要返回的值。在调用每个匿名函数时,我们传入了变量i。由于函数是按值传递的,所以会将变量i的当前值赋值给参数num,而这个匿名函数内部,又创建并返回了一个返回num的闭包。这样一来,result数组中的每个函数都有自己num的一个副本,因此就可以返回各自不同的数值了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值