关于Javascript闭包的理解
Posted simple-yu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Javascript闭包的理解相关的知识,希望对你有一定的参考价值。
以下内容属个人理解,如有看不明白或漏洞之处,纯属水平不佳,还望见谅。
关于闭包,高程里的定义是:指有权访问另一个函数作用域中的变量的函数。创建闭包最常见的方法就是在一个函数的内部再创建一个函数。
这里先创建一个函数f
function f(v1, v2) {
// 函数表达式
}
并进行调用
let result = f(5, 10)
为了搞懂闭包,首先要明白上面程序整个过程中发生了什么:
1.当调用f()函数的时候,后台创建了一个f()的执行环境与相应的作用域链(这里的作用域链的来源:在创建f()函数的时候,会创建一个预先包含了全局变量对象的作用域链,并
保存在内部的[[Scope]]属性中,当调用f()函数时,会先创建执行环境,然后通过复制[[Scope]]中的作用域链来构建自己的作用域链)
2.使用arguments和其他被命名的参数的值来初始化f()的活动对象(这里的活动对象将会被推入作用域的前端,全局变量对象始终位于最后一位,外部函数的活动对象始终位于第二位,外部函数的外部函数的活动对象始终位于第三位...以此类推,在f()函数的作用域链中包含两个变量对象:本地活动对象和全局变量对象(这里还要注意,全局变量对象是始终存在的,而本地活动对象只有在函数调用的时候才存在,同时作用域链中,仅仅是对对象的引用,而非真的包含这些对象))
3.函数调用结束后,执行环境和作用域链被销毁。
明白过程中后,我们再来看何谓闭包
这里创建一个函数f1,并在其内部返回一个匿名函数
function f1 (v1) {
return functiono (v2, v3) {
let o1 = v2 * v1
let o2 = v3 * v1
return o1 + o2
}
}
let sum = f1(5)
let result = sum(2, 3)
sum = null // 解除对匿名函数的引用,释放内存
在上述代码执行后,产生的执行环境和作用域链的关系如下图所示
(这里因为手残画图太丑,就用高程里的这张图代替...将createComparisonFunction当作f1就可以,其余变量自行脑部替换)
在 let sum = f1(5)这里,匿名函数从f1中被返回,其作用域链中包含了本地活动对象,f1的活动对象以及全局变量对象,在f1执行完毕后,执行环境被销毁,但其活动对象却不会被销毁,因为在f1返回的匿名函数的作用域链中,依旧保持着对f1活动对象的引用,只有当匿名函数也销毁了以后,才能真正的销毁所有的活动对象。
由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多,我们建议读者只在绝对必要时再考虑使用闭包。虽然像V8 等优化后的JavaScript 引擎会尝试回收被闭包占用的内存,但请大家还是要慎重使用闭包。
以上是关于关于Javascript闭包的理解的主要内容,如果未能解决你的问题,请参考以下文章