关于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 引擎会尝试回收被闭包占用的内存,但请大家还是要慎重使用闭包。
最新文章
- 虚拟机体验之 KVM 篇
- tomcat 9.0配置管理员用户名和密码
- Unity 3D
- ENode 1.0 - 消息的重试机制的设计思路
- 为什么一定要杀掉病毒?---帮一位老师解决MyDocument.exe优盘文件夹图标病毒问题
- 必须使用";角色管理工具";安装或配置microsoft.net framework 3.5
- sscanf函数和正则表达式
- js 函数定义三种方式
- MYSQL导入导出.sql文件
- 简单的优化处理 By LINQ TO SQL
- #Leet Code# Populating Next Right Pointers in Each Node II
- 在mysql中修改表名的sql语句
- 【Android】读取sdcard卡上的全部图片而且显示,读取的过程有进度条显示
- PHP使用array_intersect()函数求数组交集
- http协议中:GET/POST/PUT/DELETE/TRACE/OPTIONS/HEAD方法
- 【Spring源码深度解析学习系列】容器的基础XmlBeanFactory(二)
- Spring项目定时任务
- Tomcat 配置文件server.xml详解
- 关于Keychain
- CentOS 7下Samba服务安装与配置详解