彻底搞清js中闭包(Closure)的概念
js中闭包这个概念对于初学js的同学来说, 会比较陌生, 有些难以理解, 理解起来非常模糊. 今天就和大家一起来探讨一下这个玩意.
相信大家在看完后, 心中的迷惑会迎然而解.
闭包概念:
闭包就是有权访问另一个函数作用域中变量的函数.
分析这句话:
1.闭包是定义在函数中的函数.
2.闭包能访问包含函数的变量.
3.即使包含函数执行完了, 被闭包引用的变量也得不到释放.
例子分析-1:
function add(){
var i = 0
arr = [];
for(; i < 10; i++){
arr.push(function(){
alert(i);
});
}
return arr;
}
var temp = add();
temp[0]();
大家猜猜这个结果是多少? 0, i, 10?
我想大家会说是0.
但是结果是10.
我想大家想的应该是这样滴:
i = 0, arr.push(function(){
alert(0);
})
i = 1, arr.push(function(){
alert(1);
})
...
i = 10, arr.push(function(){
alert(10);
})
咋一看, 这个确实合理, 根据闭包的定义, 具体这个当然是上面分析的那样了.
问题就出在这个变量的理解上.
1.i是变量不假, 但是i在for循环的时候, 一直在不断变化. 也就是说这个i在参与for循环的时候, 值是不确定的, 等到for执行完后, i的值才确定.
2.每次push一个匿名函数表达式时, 那只是定义一个函数, 并没去执行那个函数, 所以那个函数里引用的外部变量都是原封不动的放进去的.
换句话说, 就是这个匿名函数在最后执行的时候, 才会去查找作用域链, 直至找到那个变量i为止.
也就是:
i = 0, arr.push(function(){
alert(i);
})
i = 1, arr.push(function(){
alert(i);
})
...
i = 10, arr.push(function(){
alert(i);
})
执行add()时, i参与循环完毕, i = 10.
执行temp[0]()时, 匿名函数会查找i, 先看自己, 我的i有值吗?没有. 再找他的上级函数, i有值吗?有, i = 10. 查找结束.
至此, 不管执行temp[0](), 还是temp[5](), 还是temp[10](), 结果都是10.
改一下上面的例子, 让它符合我们的预期要求.
例子分析-2:
function add(){
var i = 0
arr = [];
for(; i < 10; i++){
arr.push(
(function(n){
return function(){
alert(n);
}
})(i)//注意这个变化
);
}
return arr;
}
var temp = add();
temp[0]();
temp[1]();
...
这次结果是预期的,结果是 0 , 1 , 2, 3 ... 10
分析一下循环那部分.
(function(n){
return function(){
alert(n);
}
})(i)
这个叫做立即执行的匿名函数表达式(不清楚这种写法的, 可以先google下, 或者看我的单独一篇专门介绍)
i这个是时候就被当做参数传递了, 每次这个匿名函数执行时, i都会把自己的值复制一份给n
return语句中的匿名函数引用着n, 此时已经和i无关了.
每次匿名函数表达式执行时, 都会保存一个不同的n.
return语句中的匿名函数每次也引用着不同的n。
形象点就是这样:
arr.push(
(function(n = i = 0){
return function(){
alert(n = 0);
}
})(i = 0)
)
arr.push(
(function(n = i = 1){
return function(){
alert(n = 1);
}
})(i = 1)
)
...
闭包的介绍就到此为止了.
彻底搞清js中闭包(Closure)的概念的更多相关文章
- 关于js中闭包的理解
1.以前很不理解js中闭包的概念及使用,下面来看一下 function foo() { var a = 123; var b = 456; return function () { return a; ...
- 关于JS中闭包的问题
一直以来,我都以为我已经懂了JavaScript中闭包的概念,直到有一次小伙伴突然问我这个概念的时候,我才发现我根本不知道该怎来么跟他来讲述这个概念. 那时候我就知道我是自我欺骗,打肿脸充胖子了. 所 ...
- node.js中process进程的概念和child_process子进程模块的使用
进程,你可以把它理解成一个正在运行的程序.node.js中每个应用程序都是进程类的实例对象. node.js中有一个 process 全局对象,通过它我们可以获取,运行该程序的用户,环境变量等信息. ...
- js中闭包和对象相关知识点
学习js时候,读到几篇不错的博客.http://www.cnblogs.com/yexiaochai/p/3802681.html一,作用域 和C.C++.Java 等常见语言不同,JavaScrip ...
- js中闭包的概念和用法
闭包:主要的作用是 封装变量,收敛权限.防止变量被污染.比如Jquery框架就运用了大量的闭包.为什么呢? 问个问题?框架是如何来避免你声明的变量和它自带的变量不发生的冲突的?????很明显,需要闭包 ...
- js 中闭包的概念
- js中闭包的讲解
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- JS中闭包的介绍
闭包的概念 闭包就是能够读取其他函数内部变量的函数. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascri ...
- [学习笔记]JS中闭包的理解
一.闭包概念的理解 闭包,又称为词法闭包或函数闭包指引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外. 自由变量:该变量既不是函数本身定义的也不是函数 ...
随机推荐
- PHP curl 模拟登录
//提交数据,生成cookie,将cookie保存在临时目录下//在指定目录中建立一个具有唯一文件名的文件.如果该目录不存在,tempnam() 会在系统临时目录中生成一个文件,并返回其文件名 $co ...
- 我的第一个canvas的作品:漫画对白编辑器
背景:一直都对canvas挺有有兴趣的,之前刚刚看了<HTML5 CANVAS基础教程>,写了篇读书笔记. 起因:老婆发来一张最近比较热的漫画图(友谊的小船说翻就翻什么的).这种漫画,经常 ...
- STM8S003K3用Tim1的通道4输出20KHz的PWM波
void Init_pwm(){TIM1_DeInit(); TIM1_TimeBaseInit(0, TIM1_COUNTERMODE_UP, 800, 0x00);//250 TIM1_OC4In ...
- 以a为变量名,给出下列描述的定义
a)一个整型数(An integer) b) 一个指向整型数的指针(A pointer to an integer) c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to ...
- mySQL时间
" and day='".date('Y-m-d',strtotime($day_g)). "'"; 时间如: 2014-09-09 and day>= ...
- 移动APP学习笔记一
登录 ●登录用户名和密码错误时,界面有提示信息 ●用户主动退出登录后,下次启动APP时,应该进入登录界面 ●对于支持自动登录的APP,数据交换时 ,是否能自动登录成功且数据库操作无误 ●密码更改后, ...
- eclipse html插件的下载和安装
需求:需要在eclipse里面编辑html和jsp,语法高亮和语法提示,自动补全等. 1.下载GEF(依赖包): http://www.eclipse.org/downloads/download.p ...
- 关于WinForm引用WPF窗体
项目中有个界面展示用WPF实现起来比较简单,并且能提供更酷炫的效果,但是在WinForm中使用WPF窗体出现了问题,在网上找了一下有些人说Winform不能引用WPF的窗体,我就很纳闷,Win32都能 ...
- csu 1305 Substring (后缀数组)
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1305 1305: Substring Time Limit: 2 Sec Memory Limi ...
- ZOJ 3778 Talented Chef
题目链接 题意 : 这个人需要做n道菜,每道菜Ai步,他可以同时做M道不同的菜的其中一步,问你最少需要多少时间能做完所有的菜. 思路 : 这个题比赛的时候禁锢思路了,根本没想出来,就是当M > ...