疑难点总结
1.作用域是什么?
几乎所有编程语言最基本的功能之一,就是能够储存变量当中的值,并且能在之后对这个值进行访问或修改。
我们需要一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量。
这套规则被称为作用域 [scope]
每一个Javascript函数都被表示为对象,它是一个函数实例。它包含我们编程定义的可访问属性,和一系列不能被程序访问,仅供Javascript引擎使用的内部属性,其中一个内部属性是[[Scope]]
内部[[Scope]]属性包含一个函数被创建的作用域中对象的集合。此集合被称为函数的作用域链,它决定哪些数据可以由函数访问。此函数中作用域链中每个对象被称为一个可变对象,以“键值对”表示。当一个函数创建以后,它的作用域链被填充以这些对象,它们代表创建此函数的环境中可访问的数据。
2.执行上下文
对于执行上下文这个抽象的概念,可以归纳为以下几点:
- 单线程
- 同步执行
- 唯一的一个全局上下文
- 函数的执行上下文的个数没有限制
- 每次某个函数被调用,就会有个新的执行上下文为其创建,即使是调用的自身函数,也是如此。
每当调用一个函数时,一个新的执行上下文就会被创建出来。
然而,在javascript引擎内部,这个上下文的创建过程具体分为两个阶段:
-
建立阶段(发生在当调用一个函数时,但是在执行函数体内的具体代码以前)
-
建立变量,函数,arguments对象,参数
-
建立作用域链
-
确定this的值
-
-
代码执行阶段:
- 变量赋值,函数引用,执行其它代码
实际上,可以把执行上下文看做一个对象,其下包含了以上3个属性:
1
2 3 4 5 |
executionContextObj = {
variableObject: { /* 函数中的arguments对象, 参数, 内部的变量以及函数声明 */ }, scopeChain: { /* variableObject 以及所有父执行上下文中的variableObject */ }, this: {} } |
在上下文的建立阶段,先是处理arguments, 参数,接着是函数的声明,最后是变量的声明,因此变量作用域提升。