彻底搞清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中闭包的理解
一.闭包概念的理解 闭包,又称为词法闭包或函数闭包指引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外. 自由变量:该变量既不是函数本身定义的也不是函数 ...
随机推荐
- MongoDB在windows下安装配置
MongoDB的官网是:http://www.mongodb.org/ MongoDB最新版本下载在官网的DownLoad菜单下:http://www.mongodb.org/downloads 本人 ...
- laravel扩展xls处理maatwebsite/excel
github地址:https://github.com/Maatwebsite/Laravel-Excel 安装: sudo composer require maatwebsite/excel 配置 ...
- ShowMask
<html> <head> <script type="text/javascript"> function showMask(){ var a ...
- CSS溢出文本省略(text-overflow)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- EXTJS 4.2 日期控件
{ xtype: "fieldcontainer", layout: "hbox", items: [{ fieldLabel: '开始时间', name: ' ...
- IntelliJ IDEA 部署Tomcat及创建一个web工程
一.部署Tomcat 二.新建一个web工程 1.新建一个Project 2.现在建立一个简单的web工程,所以只勾选下面选中的,此外,本版本(IntelliJ IDEA 14.1.5只支持3.1版本 ...
- select框的text与value值的获取(实用版)
function def(){ var key = document.getElementById ('selectarea'); //select list var value = docum ...
- uva 125
floyd 算法 如果存在无数条路 则存在a->a的路 a->b的路径数等于 a->i 和 i->b(0=<i<=_max) 路径数的乘积和 #includ ...
- Spark的TorrentBroadcast:实现
依据Spark 1.4版 序列化和反序列化 前边提到,TorrentBroadcast的关键就在于特殊的序列化和反序列化设置.1.1版的TorrentBroadcast实现了自己的readObject ...
- 使用Web代理实现Ajax跨域
目前的工作项目分为前端和后台,双方事先约定接口,之后独立开发.后台每天开发完后在测试服务器上部署,前端连接测试服务器进行数据交互.前端和后台分开的好处是代码不用混在一个工程里一起build,互不干涉. ...