参考文献:
《JavaScript高级程序设计(第三版)》第4章+第7章
《JavaScript面向对象编程指南(第二版)》第3章
有一个比较好的链接,待看:
https://blog.csdn.net/Eternal_tyq/article/details/81914025
本文是一个初步的理解,还有待深入研究。
1.相关概念汇总
1.当创建函数时,会为函数创建一个预先包含全局变量对象的作用域链,这个作用域链保存在内部的[[scope]]属性中。
2.当调用函数时,会为函数创建一个执行环境,然后通过复制函数的[[scope]]属性中的对象构建起执行环境的作用域链。
3.此后,又有一个活动对象(在此作为变量对象使用)被创建并被推入执行环境作用域链的前端。可以看出,作用域链本质上是一个指向变量对象的指针列表。
4.作用域链是在相应的执行环境执行完毕回到主干上时就被销毁了。
5.当存在闭包时,闭包所在的包含函数执行完成后,这个执行环境的作用域链被销毁,但是闭包会引用该包含函数的变量对象,因此包含函数的变量对象没有被销毁。只有解除了对闭包函数的引用,闭包对应的包含函数的变量对象才会被销毁。
- 执行环境(execution context,环境):当函数被调用时,就形成了一个执行环境,此时函数中的变量或者函数将在程序执行到它们的时候被创建。
- 作用域链:执行环境对应一个作用域链,作用域链的本质是一个指向多个变量对象的指针列表,当执行环境结束时,作用域链被销毁。
- 变量对象:包含了this、arguments和其他命名参数的值来初始化的对象。变量对象分为全局变量对象和局部变量对象,前者为window的变量对象,后者为函数的局部对象,又称为活动对象(activation object)。
1.1 作用域链
- 内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。这些环境之间的联系是线性、有次序的。每个环境都可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。
- 执行环境的类型总共只有两种——全局和局部(函数)
- 除了使用添加函数来延长作用域链,还有两种语句能够延长作用域链
(1)try-catch 语句的catch 块;
(2)with 语句。
对上述例子的分析:
作用域链是由变量对象的引用所构成的,且每个执行环境都绑定一个作用域链和自身的变量对象,这个例子中window的执行环境是全局执行环境,作用域链只包括自身的变量对象,这里我们主要来看swapColors()这个执行环境的作用域链、changeColor()这个执行环境的作用域链。引用《JavaScript高级程序设计(第三版)》中的分析:
- 对于这个例子中的swapColors()而言,其作用域链中包含3 个变量对象:swapColors()的变量对象、c