简介

本质就是上级作用域内变量的生命周期,因为被下级作用域内引用,而没有被释放。就导致上级作用域内的变量,等到下级作用域执行完以后才正常得到释放。
闭包作用 :
- 延伸了变量的 作用范围/生命周期
- 创建私有环境 ```javascript 上级作用域变量num被下级作用域内引用(return部分函数)形成闭包,不断调用fn会一直修改num变量 function fn() { var num = 10 return function () { console.log(num); num++; } } var f = fn() f(); //10 f(); //11
//重新开启一个闭包赋值给f,输出为10 var f1 = fn() f1()//10
//继续指向闭包f函数 输出12 f(); //12
<a name="K08gw"></a># 在chrom调试下查看是否闭包<a name="mEEG8"></a># 缺点及解决1. 缺点- 函数执行完后, 函数内的局部变量没有释放, 占用内存时间会变长- 容易造成内存泄露2. 解决- 能不用闭包就不用- 及时释放```javascriptfunction fn1() {var a = 2;function fn2() {a++;console.log(a);}return fn2;}var f = fn1();f(); // 3f(); // 4f = null // 垃圾对象 释放
内存溢出&内存泄漏
- 内存溢出
- 一种程序运行出现的错误
- 当程序运行需要的内存超过了剩余的内存时, 就出抛出内存溢出的错误
- 内存泄露
- 占用的内存没有及时释放
- 内存泄露积累多了就容易导致内存溢出
常见的内存泄露:
- 意外的全局变量
- 没有及时清理的计时器或回调函数
- 闭包 ```javascript
// 1. 内存溢出 /var obj = {} for (var i = 0; i < 100000; i++) { obj[i] = new Array(10000000) } console.log(‘———‘)/
// 2. 内存泄露 // 意外的全局变量 function fn () { a = [] //不小心没有var定义 } fn() // 没有及时清理的计时器 setInterval(function () { console.log(‘——‘) }, 1000)
<a name="oFNkV"></a>
# 案例
> 此时的每个立即执行函数就在开辟了内存,所有每个i都是独立的(每个函数都是一个闭包),都要等到点击之后才会销毁,所有闭包也占内存。
<br />与上边例子原理一样<br /><br />该案例的注意点:
1. price和yd访问了上级作用域car的变量产生了闭包
1. 变量car接收了立即调用函数,此时内存空间中就有一个car和对应的变量start和total。当price被调用时修改了total=23,此时的total(23)是被price修改过后的,因此yd再执行时拿到total(23) 最后返回33。

<a name="f8Tlf"></a>
# 思考题1
左题: `object.getNameFunc().call(object)` 如果利用call改变this指向则输出的是'My Object'<br />
<a name="X0C3e"></a>
# 思考题2
该题中 有无产生闭包可以理解为 是否有被接收且未被释放<br />第一个输出 如果是 `var b = a.fun(1); b.fun(2)`则产生闭包 输出结果为//undefined,0,1,0<br />第二个输出 由于一直被接收 所以尝试了闭包<br />第三个输出 `fun(1)`后变为1,后续以c为主并且未产生闭包 所有都为1
```javascript
function fun(n, o) {
console.log(o)
return {
fun: function (m) {
return fun(m, n)
}
}
}
var a = fun(0)
a.fun(1)
a.fun(2)
a.fun(3) //undefined,0,0,0
var b = fun(0).fun(1).fun(2).fun(3) //undefined,0,1,2
var c = fun(0).fun(1)
c.fun(2)
c.fun(3) //undefined,0,1,1
