有些知识点,就像酒,时间越长理解越深。今天看波神的《前端基础进阶》有感,记录笔记如下。
执行上下文
当年看冯牙大神的《JavaScript深入之变量对象 》,对活动变量看的云里雾里的,当时也不是很理解,只是机械的记住了。今天两篇文章对照着仔细看了一下,算是明白了。
建议感兴趣的去读一下波神的那篇文章,读完能帮你解释以下几个问题:
- 变量提升和函数提升的认识
- 变量和函数声明同名时,应该等于变量还是函数?
- let/const有变量提升吗?
记录一下执行上下文的生命周期:
- 创建阶段 执行上下文会创建变量对象,确认作用域链,确定this的指向。
- 执行阶段 执行代码,完成变量赋值、函数引用,以及执行其他可执行代码。
最后推荐一下执行上下文的可视化工具:ui.dev/javascript-…
作用域
词法环境,其实就是作用域,有的人叫词法作用域等等,叫法都不是重点,重点是,不要读太多杂乱的文章,反而搞得自己更迷糊
闭包
当一个函数能够访问和操作另一个函数作用域内的变量,就形成了闭包。《前端面试宝典》
当函数可以记住并访问其所在的词法作用域(就是我们常说的那个作用域),即使函数是在当前词法作用域以外执行,这时就产生了闭包。《你不知道的javascript》
在编译过程中,JavaScript 引擎对内部函数做一次快速的词法扫描,发现该内部函数引用了 foo 函数中的 myName 变量,由于是内部函数引用了外部函数的变量,所以 JavaScript 引擎判断这是一个闭包,于是在堆空间创建换一个“closure(foo)”的对象(这是一个内部对象,JavaScript 是无法访问的),用来保存 myName 变量。《浏览器工作原理与实践-极客时间》
闭包是一种特殊的对象。它由两部分组成。执行上下文(代号A),以及在该执行上下文中创建的函数(代号B)。当B执行时,如果访问了A中变量对象中的值,那么闭包就会产生。波神《前端基础进阶》
以上几种说法都对。
- 第一种是普遍认为的说法,闭包就是操作函数外的变量。
- 第二种说法是站在函数角度来说的,闭包首先是一个函数,这个函数能干吗呢?能够记住定义时的函数作用域。所以即使在定义时的作用域以外的地方执行他,也能访问到定义时的作用域。
- 第三种说法站在内存角度,在函数编译时,分析出闭包时,会创建一个新的堆。个人理解,从原理角度讲的最好,也最符合逻辑。
- 从说人话角度讲,第四种最好记。
但闭包究竟是个啥呢,还是得从JavaScript设计实现协议里去找。可参考ECMA-262-3详解
函数与函数式编程
- 高阶函数 让普通函数获得额外能力的函数。简单来说,凡是接受一个函数作为参数的函数,就是高阶函数。
(未完待续)