-
Notifications
You must be signed in to change notification settings - Fork 65
/
闭包语义.js
45 lines (31 loc) · 2.79 KB
/
闭包语义.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**1.闭包是指有权访问另一个函数作用域中变量的函数,
* 创建闭包的常见方式就是在一个函数里面创建另一个函数
* 闭包会引用包含函数的整个活动对象
* 闭包是指那些能够访问自由变量的函数。
* 自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。
* 当某个函数被调用时 会创建一个执行环境以及相应的作用域链 使用其他命名参数和arguments来初始化函数的活动对象
* 活动对象就是下面的property和arguments
* 在作用域链中 外部对象的活动函数始终处于第二位
* 外部函数的外部函数的活动对象处于第三位 以此类推 直至作为
*
* 创建createComparison函数时 会创建一个预先包含全局变量对象的作用域链,这个作用域链保存在内部的[[scope]]属性中
* 调用createComparison函数时,会为函数创造一个执行环境 复制[[scope]]属性中的对象 构建起执行环境的作用域链
* 然后 又有一个活动对象(在此作为变量使用)被创建并且 推入执行环境作用域链的前端
* 作用域链本质上是一个指向变量对象的指针列表,它只引用但不包含实际变量对象
*
* 一般来说 当函数执行完毕之后 局部活动对象就会被销毁 内存中仅保存全局作用域
* 闭包中函数的作用域链仍然在引用这个区域的活动对象 知道闭包的函数被销毁后 她的活动对象才会被销毁
* 所以在代码最后应该结束对匿名对象的引用
* 从理论角度:所有的函数。因为它们都在创建的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问自由变量,这个时候使用最外层的作用域。从实践角度:以下函数才算是闭包:
* 1.即使创建它的'上下文'已经销毁,它仍然存在(比如,内部函数从父函数中返回)
* 2.在代码中引用了自由变量 */
/*三、闭包作用
作用1:隐藏变量,避免全局污染
作用2:可以读取函数内部的变量
同时闭包使用不当,优点就变成了缺点:
缺点1:导致变量不会被垃圾回收机制回收,造成内存消耗
缺点2:不恰当的使用闭包可能会造成内存泄漏的问题
这里简单说一下,为什么使用闭包时变量不会被垃圾回收机制收销毁呢,这里需要了解一下JS垃圾回收机制;
JS规定在一个函数作用域内,程序执行完以后变量就会被销毁,这样可节省内存;
使用闭包时,按照作用域链的特点,闭包(函数)外面的变量不会被销毁,因为函数会一直被调用,所以一直存在,如果闭包使用过多会造成内存销毁。
*/