根据一段代码浅谈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
Aug 13 Javascript
JS判断页面加载状态以及添加遮罩和缓冲动画的代码
Oct 11 Javascript
js实现页面转发功能示例代码
Aug 05 Javascript
javascript编写贪吃蛇游戏
Jul 07 Javascript
jquery实现的用户注册表单提示操作效果代码分享
Aug 28 Javascript
浅谈Javascript中Object与Function对象
Sep 26 Javascript
jQuery实现大图轮播
Feb 13 Javascript
在 Node.js 中使用 async 函数的方法
Nov 17 Javascript
详解webpack4多入口、多页面项目构建案例
May 25 Javascript
jQuery实现经典的网页3D轮播图封装功能【附源码下载】
Feb 15 jQuery
解决vue语法会有延迟加载显现{{xxx}}的问题
Nov 14 Javascript
vue实现短信验证码登录功能(流程详解)
Dec 10 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
Notice: Undefined index: page in E:\PHP\test.php on line 14
2010/11/02 PHP
PHP sprintf()函数用例解析
2011/05/18 PHP
关于PHP session 存储方式的详细介绍
2013/06/25 PHP
ThinkPHP实例化模型的四种方法概述
2014/08/22 PHP
PHP SPL标准库之文件操作(SplFileInfo和SplFileObject)实例
2015/05/11 PHP
php实现基于PDO的预处理示例
2017/03/28 PHP
Windows平台实现PHP连接SQL Server2008的方法
2017/07/26 PHP
TP5框架实现自定义分页样式的方法示例
2020/04/05 PHP
JQuery Dialog(JS 模态窗口,可拖拽的DIV)
2010/02/07 Javascript
原生js结合html5制作简易的双色子游戏
2015/03/30 Javascript
JavaScript正则表达式之multiline属性的应用
2015/06/16 Javascript
JavaScript高级教程5.6之基本包装类型(详细)
2015/11/23 Javascript
jQuery实现下拉加载功能实例代码
2016/04/01 Javascript
javascript中this指向详解
2016/04/23 Javascript
微信开发 js实现tabs选项卡效果
2016/10/28 Javascript
jQuery中get方法用法分析
2016/12/07 Javascript
angular.JS实现网页禁用调试、复制和剪切
2017/03/31 Javascript
js操作二进制数据方法
2018/03/03 Javascript
vue的传参方式汇总和router使用技巧
2018/05/22 Javascript
JS逻辑运算符短路操作实例分析
2018/07/09 Javascript
layui实现图片虚拟路径上传,预览和删除的例子
2019/09/25 Javascript
python算法学习之基数排序实例
2013/12/18 Python
Python编写简单的HTML页面合并脚本
2016/07/11 Python
python中OrderedDict的使用方法详解
2017/05/05 Python
详解Python装饰器
2019/03/25 Python
Python paramiko 模块浅谈与SSH主要功能模拟解析
2020/02/29 Python
Python爬虫爬取百度搜索内容代码实例
2020/06/05 Python
python学习将数据写入文件并保存方法
2020/06/07 Python
解决c++调用python中文乱码问题
2020/07/29 Python
酒店中秋节活动方案
2014/01/31 职场文书
2014年两会学习心得体会
2014/03/10 职场文书
年度安全生产目标责任书
2014/07/23 职场文书
司机工作自我鉴定
2014/09/19 职场文书
会计工作检讨书
2015/02/19 职场文书
2015毕业实习推荐信
2015/03/23 职场文书
数据结构课程设计心得体会
2016/01/15 职场文书