根据一段代码浅谈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 相关文章推荐
js检测客户端不是firefox则提示下载
Apr 07 Javascript
jQuery 学习第五课 Ajax 使用说明
May 17 Javascript
javascript实现的使用方向键控制光标在table单元格中切换
Nov 17 Javascript
Js日期选择自动填充到输入框(界面漂亮兼容火狐)
Aug 02 Javascript
JS禁用浏览器退格键实现思路及代码
Oct 29 Javascript
使用jquery animate创建平滑滚动效果(可以是到顶部、到底部或指定地方)
May 27 Javascript
jQuery实现Flash效果上下翻动的中英文导航菜单代码
Sep 22 Javascript
js实现网页收藏功能
Dec 17 Javascript
vue之浏览器存储方法封装实例
Mar 15 Javascript
详解vue的数据劫持以及操作数组的坑
Apr 18 Javascript
微信小程序上传图片并等比列压缩到指定大小的实例代码
Oct 24 Javascript
JS数组方法join()用法实例分析
Jan 18 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
深入了解php4(2)--重访过去
2006/10/09 PHP
深入apache配置文件httpd.conf的部分参数说明
2013/06/28 PHP
关于JSON以及JSON在PHP中的应用技巧
2013/11/27 PHP
php代码审计比较有意思的例子
2014/05/07 PHP
javascript与CSS复习(二)
2010/06/29 Javascript
在网页中使用document.write时遭遇的奇怪问题
2010/08/24 Javascript
Shell脚本实现Linux系统和进程资源监控
2015/03/05 Javascript
JavaScript时间转换处理函数
2015/04/14 Javascript
JavaScript调用传递变量参数的相关问题及解决办法
2015/11/01 Javascript
扩展Bootstrap Tooltip插件使其可交互的方法
2016/11/07 Javascript
原生JavaScript实现Ajax异步请求
2017/11/19 Javascript
浅谈Vue响应式(数组变异方法)
2018/05/07 Javascript
JavaScript callback回调函数用法实例分析
2018/05/08 Javascript
详解如何使用node.js的开发框架express创建一个web应用
2018/12/20 Javascript
Vue使用axios出现options请求方法
2019/05/30 Javascript
新手入门带你学习JavaScript引擎运行原理
2019/06/24 Javascript
vue中后端做Excel导出功能返回数据流前端的处理操作
2020/09/08 Javascript
Python之py2exe打包工具详解
2017/06/14 Python
Python3.6简单操作Mysql数据库
2017/09/12 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
2019/07/11 Python
PyTorch中Tensor的维度变换实现
2019/08/18 Python
Python3 sys.argv[ ]用法详解
2019/10/24 Python
python tqdm实现进度条的示例代码
2020/11/10 Python
CSS3动画:5种预载动画效果实例
2017/04/05 HTML / CSS
英国在线电子和小工具商店:TecoBuy
2018/10/06 全球购物
北京华建集团SQL面试题
2014/06/03 面试题
大学生军训广播稿
2014/01/24 职场文书
大学生简短的自我评价分享
2014/02/20 职场文书
学习决心书范文
2014/03/11 职场文书
应聘编辑自荐信范文
2014/03/12 职场文书
社会工作专业求职信
2014/07/15 职场文书
运动会加油稿100字
2014/09/19 职场文书
基层党员对照检查材料
2014/09/24 职场文书
检讨书大全
2015/01/27 职场文书
深入理解python协程
2021/06/15 Python
24年收藏2000多部退役军用电台
2022/02/18 无线电