JavaScript闭包理解【关键字:普通函数、变量访问作用域、闭包、解决获取元素标签索引】
一、闭包(Closure)模糊概述
之前总觉得闭包(Closure)很抽象而且难理解,百度一下"闭包"名词,百度的解释是:“闭包是指可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)”
看了半天,也没有看懂闭包是什么?以下将是我对闭包(Closure)的理解,如有错误欢迎指出
二、普通函数、变量访问作用域
以上普通函数的调用fn被调用了两次,变量b却没有累加??
对于函数f1变量b在函数外部是不能访问的
如若实现局部变量b的累加,并且可以访问该怎么做呢?
三、闭包(Closure)的清晰描述
(1)闭包(Closure)简单的可以理解成函数的嵌套,闭包就是能够读取其他函数内部变量的函数。
(2)变量长期驻留在内存中
、
以上可以看出,父函数f1中的变量b对于子函数f2是可访问的或者说是可见的,父函数f1调用一次,意味着变量b始终都是同一变量,f2中的b++,实现了对同一变量的自加,
对于子函数f2形成一个最简单的闭包(或者说函数f2维持着对外部作用域f1的引用,因此总可以访问f1作用域中的变量b)
三、闭包在对象中应用
、
四、解决获取标签索引问题
需求:当点击点击标签li时,获取标签li的内容及索引
a.理想中的方案一<未使用闭包,未解决索引值问题>
效果:未解决获取到当前点击标签对应索引值,获取到的索引总是for循环完毕后的索引i
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>未使用闭包获取标签索引</title>
<script type="text/javascript">
window.onload=function(){
var oLi=document.getElementsByTagName('li');
for (var i = 0; i < oLi.length; i++) {
oLi[i].onclick=function(){//当点击li的时候,for循环已经执行完毕
alert(this.innerHTML+'index'+i);//总是i==5
}
};
}
</script>
</head>
<body>
<ul>
<li>AAA</li>
<li>BBB</li>
<li>CCC</li>
<li>DDD</li>
<li>EEE</li>
</ul>
</body>
</html>
b.解决方案二<使用闭包>代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>闭包解决获取标签索引问题</title>
<script type="text/javascript">
window.onload=function(){
var oLi=document.getElementsByTagName('li');
/*for (var i = 0; i < oLi.length; i++) {
oLi[i].onclick=(function(i){ //就已经存储到缓冲中
return function(){
alert(this.innerHTML+'index'+i);
}
})(i)
};*/
for (var i = 0; i < oLi.length; i++) {
(function(i){
oLi[i].onclick=function(){
alert(this.innerHTML+'index'+i);
}
})(i)
};
}
</script>
</head>
<body>
<ul>
<li>AAA</li>
<li>BBB</li>
<li>CCC</li>
<li>DDD</li>
<li>EEE</li>
</ul>
</body>
</html>
五、一道思考题(for循环与setTimeout)
上述打印结果打印了10次10,而不是0~9
原因 当 console.log
被调用的时候,匿名函数保持对外部变量 i
的引用,此时 for
循环已经结束, i
的值被修改成了 10
.
为了打印结果是0~9,需要在每次循环时创建变量i的拷贝修改代码如下
或修改成如下
资料参考
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
http://www.jb51.net/onlineread/JavaScript-Garden-CN/#function.closures
最新文章
- 1051. Pop Sequence
- Python验证码6位自动生成器
- PHP表单与验证
- 查看 table,view,sp的定义
- Symbol ES6 新增的一种值类型数据,表示一种绝不重复的值
- [机器学习]信息&;熵&;信息增益
- c++ 文件读写模板
- 快餐店运行模拟C++程序源码代写
- sonarQube Scanner
- 03 - 替换vtkDataObject中的GetProducerPort()方法 VTK 6.0 迁移
- 【原创】ZOJ_1649 Rescue 解题报告
- UVA 1411 - Ants(二分图完美匹配)
- 深入理解C指针之六:指针和结构体
- 简单使用Markdown
- xc笔记
- 关于Kafka java consumer管理TCP连接的讨论
- Vue的理解:Vue.js新手入门指南----转
- array与xml转换实现(转)
- Centos6.9下RabbitMQ集群部署记录
- 尚学堂java 答案解析 第六章
热门文章
- [转]Angular: Hide Navbar Menu from Login page
- C# CLR via 对象内存中堆的存储【类型对象指针、同步块索引】
- c# 后台分页 jqgrid
- [angularjs] angularjs系列笔记(八)事件
- Netty 系列九(支持UDP协议).
- JavaScript 笔记(一)
- 设计模式之原型模式——Java语言描述
- unable to locate nuget.exe
- canvas-7globleCompositeOperation.html
- js 分页插件(jQuery)