简介

  一个定义在函数内部的函数与包含它的外部函数构成了闭包,内部函数可以访问外部函数的变量,这些变量将一直保存在内存中,直到无法再引用这个内部函数。

例如:

var a = 0;
function outerFun(i) {
var b = i;
function innerFun(j) {
var c = j;
console.log("全局变量:"+a);
console.log("外部变量:"+b);
console.log("内部变量:"+c);
a++;
b++;
c++;
}
return innerFun;
}
var testFun1 = outerFun(10);
testFun1(10);//全局变量:0 外部变量:10 内部变量:10
testFun1(10);//全局变量:1 外部变量:11 内部变量:10 var testFun2 = outerFun(20);
testFun2(20);//全局变量:2 外部变量:20 内部变量:20
testFun2(20);//全局变量:3 外部变量:21 内部变量:20

结论:

c 是 innerFun() 的局部变量,每次执行 innerFun() 都会重新赋值;
b 是 innerFun() 的上一级变量,每次执行 innerFun() 的结果会保存在内存中,是 outerFun() 的局部变量,每次执行 outerFun() 都会重新赋值;
a 是 innerFun() 的上上一级变量,每次执行 innerFun() 的结果会保存在内存中,是 outerFun() 的上一级变量,每次执行 outerFun() 的结果也会保存在内存中;

  在JavaScript中,作用域只有全局作用域和函数级作用域两种,在下一级作用域中可以访问和修改上一级作用域的变量,在定义函数时,JS会自动维护一个作用域链,当前的局部作用域位于作用域链顶端,并可以依次向上回溯。闭包的实质就是延长了作用域链。

变量的生存周期

  上面提到,js 中只有全局变量和函数级的局部变量两种,全局变量的生存周期当然是永久的,除非我们主动销毁这个全局变量。而对于在函数内用 var 关键字声明的局部变量来说,当退出函数时,这些局部变量即失去了它们的价值,它们都会随着函数调用的结束而被销毁。

例如:

//页面有5个 div,期望点击每个 div 输出它的序号
for(var i=0; i<5; i++) {
$('div').eq(i).on('click',function() {
console.log(i);
})
}

然而,实际上,点击每个 div 输出的都是5,这是因为 i 是全局变量,位于作用域链最顶端,当改变 i 的值的时候,所有引用了它的函数都会受到影响,当循环运行结束后,i 的最终值为5,所以点击每个 div 输出的当然是5了。这时我们可以通过闭包来延长作用域链,为 i 的值保存一个副本,使它们之间不会互相影响。

例如:

for(var i=0; i<5; i++) {
function outerFun() {
var j = i;
function innerFun() {
$('div').eq(j).on('click',function() {
console.log(j);
})
}
innerFun();
}
outerFun();
}

这里的 outerFun() 和 innerFun() 都可以用匿名自执行函数代替,例如:

for(var i=0; i<5; i++) {
(function() {
var j = i;
(function() {
$('div').eq(j).on('click',function() {
console.log(j);
})
})();
})();
}

最新文章

  1. Kafka vs RocketMQ—— Topic数量对单机性能的影响-转自阿里中间件
  2. java提升路线书单(原文自知乎刘欣)
  3. 大公司的PHP面试题
  4. 触发Full GC执行的情况
  5. HUSTOJ搭建实录
  6. html基础总结版
  7. hdu 5585 Numbers
  8. Nmap备忘单:从探索到漏洞利用(Part3)
  9. 关于form.submit()不能提交表单的错误原因
  10. DataList嵌套绑定例子
  11. C语言信号学习笔记
  12. Json字符串转Json对象
  13. [Mark] KVM 虚拟化基本原理
  14. sf中标准的分页功能介绍
  15. 关于combotree的用法总结
  16. laravel整合JWT遇到的问题及解决方案
  17. RS232串口的Windows编程纪要
  18. latex 导入pdf
  19. Python的二叉树实现
  20. python------模块定义、导入、优化 -------&gt;re模块

热门文章

  1. 百度的android面试总结分析
  2. (Tomcat)服务器之web应用的虚拟目录映射和主机搭建
  3. JAVA之旅(二十)—HashSet,自定义存储对象,TreeSet,二叉树,实现Comparator方式排序,TreeSet小练习
  4. ad network
  5. JAVA之旅(十二)——Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口
  6. 关于reverse_iterator
  7. awk字符串函数及其意义
  8. Miner.java 爬虫启动类
  9. JVM学习笔记 -- 从一段几乎所有人代码都会犯错的代码开始
  10. Java集合之Stack