根据一段代码浅谈Javascript闭包


Posted in Javascript onDecember 14, 2010
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 限制输入脚本大全
Nov 03 Javascript
jQuery模拟超链接点击效果代码
Apr 21 Javascript
JS随机漂浮广告代码具体实例
Nov 19 Javascript
Javascript中的异步编程规范Promises/A详细介绍
Jun 06 Javascript
jQuery实现文字自动横移
Jan 08 Javascript
AngularJS中的拦截器实例详解
Apr 07 Javascript
jQuery手风琴的简单制作
May 12 jQuery
React-router 4 按需加载的实现方式及原理详解
May 25 Javascript
微信公众号H5支付接口调用方法
Jan 10 Javascript
浅谈对于react-thunk中间件的简单理解
May 01 Javascript
js实现列表按字母排序
Aug 11 Javascript
详解JavaScript中的链式调用
Nov 27 Javascript
js保存当前路径(cookies记录)
Dec 14 #Javascript
利用JQuery的load函数动态加载其它页面的内容的实现代码
Dec 14 #Javascript
Jquery练习之表单验证实现代码
Dec 14 #Javascript
基于Jquery的淡入淡出的特效基础练习
Dec 13 #Javascript
Juqery Html(),append()等方法的Bug解决方法
Dec 13 #Javascript
JQuery中getJSON的使用方法
Dec 13 #Javascript
JavaScript 学习历程和心得分享
Dec 12 #Javascript
You might like
2020最新CPU的性能排名
2020/04/02 数码科技
谈谈PHP语法(5)
2006/10/09 PHP
php批量删除数据
2007/01/18 PHP
实用函数7
2007/11/08 PHP
用PHP实现Ftp用户的在线管理
2012/02/16 PHP
php中取得文件的后缀名?
2012/02/20 PHP
PHP curl 并发最佳实践代码分享
2012/09/05 PHP
探讨PHP删除文件夹的三种方法
2013/06/09 PHP
PHP 错误处理机制
2015/07/06 PHP
Thinkphp批量更新数据的方法汇总
2016/06/29 PHP
laravel migrate初学常见错误的解决方法
2017/10/11 PHP
Laravel多用户认证系统示例详解
2018/03/13 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
2020/03/24 PHP
Javascript注入技巧
2007/06/22 Javascript
javascript Array.prototype.slice的使用示例
2013/11/14 Javascript
JavaScript实现大数的运算
2014/11/24 Javascript
Jquery 实现checkbox全选方法
2015/01/28 Javascript
d3.js实现简单的网络拓扑图实例代码
2016/11/06 Javascript
JavaScript判断浏览器及其版本信息
2017/01/20 Javascript
JS中min函数实例讲解
2019/02/18 Javascript
vue.js 实现a标签href里添加参数
2019/11/12 Javascript
JavaScript实现与web通信的方法详解
2020/08/07 Javascript
[02:50]2014DOTA2 TI预选赛预选赛 大神专访第一弹!
2014/05/21 DOTA
[46:04]Liquid vs VP Supermajor决赛 BO 第四场 6.10
2018/07/05 DOTA
Python中实现三目运算的方法
2015/06/21 Python
VScode编写第一个Python程序HelloWorld步骤
2018/04/06 Python
Python参数传递实现过程及原理详解
2020/05/14 Python
keras做CNN的训练误差loss的下降操作
2020/06/22 Python
python中return不返回值的问题解析
2020/07/22 Python
python中翻译功能translate模块实现方法
2020/12/17 Python
CSS3绘制不规则图形的一些方法示例
2015/11/07 HTML / CSS
美国优质马术服装购买网站:Breeches.com
2019/12/16 全球购物
联谊活动策划书
2014/01/26 职场文书
深入开展党的群众路线教育实践活动方案
2014/02/04 职场文书
收款委托书
2014/10/14 职场文书
2019年教师节:送给所有老师的祝福语
2019/09/05 职场文书