js的嵌套函数与闭包函数

先看一下代码示例:

function f(){
var cnt=0;
return function(){ return ++cnt;}
}
var fa=f();//将函数f的的返回值给变量fn
// fa();    //对fn的函数调用
console.log(fa());//1
console.log(fa());//2
console.log(fa());//3

函数的返回值是函数(对象的引用),这里将其赋值给变量fn。在调用fn时,其输出结果每次都会自增加1

从表面看,闭包(closure)具有状态的函数,或者也可以将闭包的特征理解为:其相关的局部变量在函数调用结束后会继续存在

一、闭包的原理

   1.1 嵌套的函数声明:

闭包的前提条件是需要在函数声明的内部声明另一个函数(即嵌套的函数声明)贴一下函数函数声明的simple example:

function f(){
    function g(){
       console.log('g is called');
    }
   g();
}
f()// g is called

在函数f的声明中包含函数g的声明以及调用语句。再调用函数f时,就间接地调用了函数g。为了更好理解该过程,在此对其内部机制进行说明。

在javaScript中,调用函数时将会隐式地生成call对象。为了方便起见,我们将调用函数f生成的call对象称作call-f对象。在函数调用完成之后,call对象将被销毁。

函数f内的函数g的声明将会生成一个与函数的g相对应function对象。其名称g是call-f对象的属性。由 于每一次调用函数都会独立生成call对象,因此在调用函数g时将会隐式地生成另一个call对象。为了方便起见,我们将该call对象称作call-g对象。

离开函数g之后,call-g对象将被自动销毁。类似的,离开函数f之后,call-f对象也就自动销毁。此时,由于属性g将与call-g对象一起被销毁,所以由g所引用的function对象将会失去其引用,而最终(通过垃圾回收机制)被销毁。

1.2嵌套函数与作用域

对上面代码稍稍修改:

function f(){
    var n=123;
    function g(){
        console.log("n is"+n);
        console.log('g is called');
    }
    g();
}
f();

运行结果:

js>f();

n is 123

g is called'

在内层进行声明函数g可以访问外层的函数f的局部变量(在这里指变量n),对于嵌套声明的函数,内部的函数将会首先查找被调用时所生成的call对象的属性,之后之后在查找外层函数的call对象的属性。这一机制被称为作用链。

1.3嵌套函数的返回

上面的代码稍稍修改

function f(){
    var n=123;
    function g(){
        console.log("n is"+n);
        console.log('g is called');
    }
    return g;
}
js> f();

function g(){
        console.log("n is"+n);
        console.log('g is called');
    }

由于return语句,函数将会返回一个function对象(的引用)。调用函数f的结果是一个function对象。这时,虽然会生成与函数f相对应的call对象(call-f对象)(并在离开函数f后被销毁),但由于不会调用函数g,所以此时还不会生成与之相对应的call对象(call-g对象),请对此多加注意。

1.4闭包

js>var g2=f();

jd>g2();

n is 123//将返回的函数赋值给变量

g is called//调用函数(函数f内函数g)

 

转载于:https://www.cnblogs.com/pikachuworld/p/5325868.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值