根据一段代码浅谈Javascript闭包

 更新时间:2010年12月14日 21:42:45   作者:  
水平不高,不能也不想从太深的层次去讲解这个东西,只是根据一段比较有代表性的代码,结合执行结果,从表象上粗浅地谈谈。
复制代码 代码如下:

function f1(){
var n = 999;
nAdd = function(){ n += 1; }
function f2(){
alert(n);
}
return f2;
}

这里的闭包是f1,封闭了一个变量n和一个函数f2。

我们先无视nAdd,尽量保持原貌重写一下这个函数。
复制代码 代码如下:

function f1(){
var n = 999;
var f2 = function(){ alert(n); };
return f2;
}
var result = f1();
result();

js中各个变量以function为单元进行封装,当在function内部找不到某一变量时,function会向其所在的上一单元(上下文)中进行查找,一直查找到顶层的window域。
这时就出现一个疑问:这个查找过程是以函数引用位置为起点还是函数体定义的位置为起点?
在上面这一段代码中,result所在域是window,但是实际的输出结果是f1内部的n值,所以可以得出结论:变量查找的起点是函数体定义的位置。

现在再回过头来看nAdd(第一段代码)。如我们所知,没有关键字var定义的变量默认进入window域,所以nAdd实际为window.nAdd。这就等同于如下代码:
复制代码 代码如下:

var nAdd;
function f1(){
var n = 999;
nAdd = function(){ n += 1; }
function f2(){
alert(n);
}
return function(){ alert(n); };
}

那么根据我们对result的分析,nAdd的执行将影响f1中n的值。
所以有:
复制代码 代码如下:

function f1(){
var n = 999;
nAdd = function(){ n += 1; }
function f2(){
alert(n);
}
return function(){ alert(n); };
}
var result = f1();
result();
nAdd();
result();

这段代码执行最终的输出结果为1000。

再看这种情况:
复制代码 代码如下:

function f1(){
var n = 999;
nAdd = function(){ n += 1; }
function f2(){
alert(n);
}
return function(){ alert(n); };
}

f1()(); //<--p1
nAdd();
f1()(); //<--p2

简述一下执行过程:
p1位置,f1封装了一个匿名的闭包A,在返回A闭包中的函数A:f2后继而执行A:f2,A:f2输出变量A:n,结果是999。
与此同时,nAdd被赋值为A闭包中的一个函数,下一行执行nAdd即让A:n的值+1。
p2位置,f1封装匿名的闭包B,所进行的操作都是针对闭包B的,随后执行B:f2输出的是B:n,所以最后的结果依然是999。
A和B是两个独立的“包”,互不影响。

改写一下函数的调用部分:

复制代码 代码如下:

function f1(){
var n = 999;
nAdd = function(){ n += 1; }
function f2(){
alert(n);
}
return function(){ alert(n); };
}

var result = f1();
result();
nAdd();
f1()();
result(); // <--p3

p3位置不意外地输出了1000。

相关文章

  • 谈谈javascript中使用连等赋值操作带来的问题

    谈谈javascript中使用连等赋值操作带来的问题

    这篇文章主要介绍了javascript中使用连等赋值操作带来的问题的相关资料,需要的朋友可以参考下
    2015-11-11
  • 使用微信小程序开发弹出框应用实例详解

    使用微信小程序开发弹出框应用实例详解

    本文通过实例代码给大家介绍了使用微信小程序开发弹出框功能,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-10-10
  • js+html5实现可在手机上玩的拼图游戏

    js+html5实现可在手机上玩的拼图游戏

    这篇文章主要介绍了js+html5实现可在手机上玩的拼图游戏,涉及javascript结合html5进行图形操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • JavaScript词法作用域与调用对象深入理解

    JavaScript词法作用域与调用对象深入理解

    关于 Javascript 的函数作用域、调用对象和闭包之间的关系很微妙,关于它们的文章已经有很多,本文做了一些总结,需要的朋友可以参考下
    2012-11-11
  • 简述JS浏览器的三种弹窗

    简述JS浏览器的三种弹窗

    本文给大家简单介绍了JS浏览器的三种弹窗,简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-07-07
  • Bootstrap复选框和单选按钮美化插件(推荐)

    Bootstrap复选框和单选按钮美化插件(推荐)

    这篇文章主要介绍了Bootstrap复选框和单选按钮美化插件的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-11-11
  • 关于iframe跨域POST提交的方法示例

    关于iframe跨域POST提交的方法示例

    这篇文章主要给大家介绍了关于iframe跨域POST提交的相关资料,文中给出了详细的介绍与示例代码,相信对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以一起来学习学习。
    2017-01-01
  • js仿京东放大镜效果

    js仿京东放大镜效果

    这篇文章主要为大家详细介绍了js仿京东放大镜效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-08-08
  • JavaScript转换农历类实现及调用方法

    JavaScript转换农历类实现及调用方法

    农历是日常生活中不可或缺的一部分,它与人类的生活息息相关,从某种程度上说,它一直伴随着我们,今天的任务是JavaScript转换农历类的实现,感兴趣的你可以千万不要错过,希望本文对你有所帮助
    2013-01-01
  • 微信小程序实现Session功能及无法获取session问题的解决方法

    微信小程序实现Session功能及无法获取session问题的解决方法

    这篇文章主要介绍了微信小程序实现Session功能及无法获取session问题的解决方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05

最新评论