作用域
词法作用域和动态作用域
我们需要先了解一个概念便是Js采用的是词法作用域,而不是动态作用域。
- 词法作用域:
词法作用域就是定义在词法阶段的作用域,是由写代码时将变量和块作用域写在哪里来决定的。无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处的位置决定。
- 动态作用域:
动态作用域并不关心函数和作用域是如何声明以及在任何处声明的,只关心它们从何处调用。换句话说,作用域链是基于调用栈的,而不是代码中的作用域嵌套。
Js中的作用域
- 全局作用域
- 函数作用域
- 块级作用域(ES6所提出的概念,新增了let和const来解决var的问题)
var count = 100; //全局作用域
function foo() {
var count = 0; //函数作用域
return count;
}
if (count == 1) {
//块级作用域
let a = 1;
a = a + count
}
作用域:作用域是一套规则,用来确定在何处以及如何查找标识符。
作用域链本质是一个指向变量对象的指针列表。
作用域链和自由变量
作用域链
- 基本概念:Js的函数作用域是可以互相嵌套的,各个作用域的嵌套关系便组成了一条作用域链。
- 作用域的作用:作用域链的主要作用便是进行标识符的查询。当一个函数内部对一个变量进行操作,这时候Js内部便会从当前函数的作用域开始一层一层向外查找该标识符,直到查询到作为作用域的终点的全局执行环境。
- 如果自身作用域中声明该变量,则无需使用作用域链。
- 如果自身作用域中未声明该变量,则需要使用作用域链进行查找。这时,我们再看下一个概念自由变量
自由变量
概念:在当前作用域中存在但未在当前作用域中声明的变量叫自由变量
执行环境和变量对象
在网上看到了这样一句话,可以供大家参考一下:
当函数被创建,就有了作用域,当被调用时,就有了作用域链,当被继承时就有了原型链,当需要获取作用域链或原型链上的变量或值时,就有了闭包。
- 当一个函数被声明时会创建该函数的作用域,同时会创建一个预先包含全局变量对象的作用域链。该作用域链被保存在内部的[[Scope]]属性中。
- 当一个函数被调用的时候会为该函数创建一个执行环境(执行上下文),然后通过复制函数的[[Scope]]属性中的对象构建起环境作用域链的前端。执行上下文的周期又分为两部分:
- 创建部分:创建变量对象(环境中定义的所有变量和函数都保存在这个对象中。),确定它的作用域链,确定它的this的指向。
- 执行部分:确定变量对象的值。然后将函数引用,执行其他代码。
- 变量对象的创建过程:
- 建立一个argunments对象,寻找当前上下文中的参数,并以其参数名以及参数值创建一个属性。
- 寻找当前上下文当中的function声明,在变量对象中,以函数名为属性名,创建以个属性,值为函数的引用地址,如果函数名重复的话,后面的覆盖前面的。
- 寻找当前上下文当中的var声明,在变量对象中,以变量名为其属性名,创建以个属性,值为undefined。
- 执行环境和变量对象的区别:执行环境和变量对象。执行环境会随着函数的调用和返回,不断的重建和销毁。但变量对象在有变量引用的情况下,将留在内存中不被销毁。
执行流
- 概念:代码的执行顺序叫做执行流,程序源代码并不是按照代码的书写顺序一行一行往下执行,而是和函数的调用顺序有关。
- 示例:
var a = 1;
var b = 2;
function fn (x) {
console.log(x);
function add(y) {
var c = 3;
var count = y + c;
return count;
}
var d = bar(10) // 第十行
console.log(d)
}
fn(20)
如上代码,请执行顺序为:
第一行->第二行->第三行->最后一行->第四行->第五行->第十行->进入add()函数里执行->第十一行->第十二行
执行环境栈
我们知道,当我们每调用一个函数便会创建一个执行环境,当我们调用的函数多了,便会创建多个执行环境。Js引擎创建了执行环境栈来保存这些执行环境。
可以把执行上下文栈认为是一个存储函数调用的栈结构,遵循先进后出的原则。
下面来看一张图(该图从网上获取):
从上面的流程图,我们需要记住几个关键点:
- JavaScript 执行在单线程上,所有的代码都是排队执行。
- 一开始浏览器执行全局的代码时,首先创建全局的执行上下文,压入执行栈的顶部。
- 每当进入一个函数的执行就会创建函数的执行上下文,并且把它压入执行栈的顶部。当前函数执行完成后,当前函数的执行上下文出栈,并等待垃圾回收。
- 浏览器的 JS 执行引擎总是访问栈顶的执行上下文。
- 全局上下文只有唯一的一个,它在浏览器关闭时出栈。
参考文章:
参考书籍:
JavaScript高级程序设计