小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
10/13对例子与部分知识点进行更新&增添
学习了一下闭包~
- 先来看个最简单的例子
function Fun(){
var a = 1;
function foo(){
console.log(a);
}
}
console.log(Fun());// undefined
// 由于内部函数调用 产生了闭包
当嵌套的内部函数引用了外部函数的变量时就产生了闭包
闭包形成过程如下:
参考:详细解析 JavaScript 闭包 这篇文章真的非常全面 后面还配有一些不错的例子
很明显这个过程发生了函数提升!
通过chrome工具得知: 闭包本质是内部函数中的一个对象, 这个对象中包含引用的变量属性(上图中的a 且值为undefined)
再举一个复杂一些的例子
function Fun(){
var a = 1;
function foo(){
a++;
console.log(a);
}
return foo
}
var f = new Fun();
f();// 2
f();// 3
// 过程中foo被解析 调用了全局变量a 形成闭包(闭包对象为Fun)
其中发生的过程大家可以自行打断点看一下
比较重要的点是:
不管在Fun()函数中各个部分的a值为多少,在赋值语句 a=1 亮相的一刹那(就是a = 1执行发生时),所有a变为1
这一点在下面的代码中体现得很明显
10/13补充
需要额外注意一下, 上面那个例子使用 var foo = function(){}输出的结果相同,但是过程是有区别的!!
function Fun(){
var a = 1;
var foo = function(){
a++;
console.log(a);
}
return foo
}
var f = new Fun();
f();// 2
f();// 3
打个断点看看
害!虽然在本例中输出结果都是一样的,但是有的问题中,这种给变量赋一个函数的方式与用function声明函数的最终输出是不同的!
本例中需要明白二者在执行时有何差异~!
小结下闭包形成的条件——
- 【1】函数嵌套
- 【2】内存函数中有(引用了)外层函数的变量(/函数)
闭包作用、应用、缺点
于10/13精简 + 完善 “闭包的缺点”部分内容
-
闭包作用
- 延长局部变量的生命周期
- 让函数外部能操作内部的局部变量
-
闭包的应用
-
模块化——
- 封装一些数据/操作数据的函数 向外暴露一些行为
-
循环遍历 + 监听
-
JS框架(jQuery)中大量使用了闭包
-
-
闭包的缺点
- 可能导致内存溢出(面试高频)
var obj = {}; for(var i = 0; i < 10000; i++){ obj[i] = new Array(1000000);// new Array(1000000)定义一个长度为1000000的数组 console.log('------') }// 这个代码会导致内存溢出 浏览器会做一个崩溃的设置 终止程序内存溢出是指存储的数据超出了指定空间的大小,这时数据就会越界
- 可能会导致内存泄露
function fn1(){ var arr = new Array[10000000] function fn2(){ console.log(arr.length); } return fn2; } var f = fn1(); f();// fn1形成闭包 本该释放的arr变量现在不会被释放!内存泄漏的意思:变量占用内存的事件可能会过长(毕竟延长了局部变量的生命周期嘛~ 申请的内存空间没有被正确释放,导致后续程序里这块内存被永远占用(不可达))——
所以需要及时释放
让内部函数对象f成为垃圾对象!!
f = null;// 解放空间!