JS 温故而知新——揭秘执行上下文与执行栈的机制
2023-09-29 23:32:23
执行上下文,在Javascript里是一个很重要的概念
Javascript是一种单线程语言,这意味着它一次只能执行一个任务,这个任务就是一个执行上下文,当这个任务完成时,才会执行下一个任务。
执行上下文主要由两部分组成
- 变量对象 :保存着该执行上下文下所有声明的变量和函数,这个对象也就是词法环境(Lexical Environment)。
- 作用域链 :保存着该执行上下文和它的所有父执行上下文的变量对象,作用域链用来解析变量,当一个变量在当前执行上下文中找不到时,就会沿着作用域链向上查找。
执行栈(又名调用栈)是一个存储执行上下文的后进先出栈(Last In First Out,LIFO),当一个函数被调用时,一个新的执行上下文就被创建并压入执行栈中,当函数返回时,执行上下文被弹栈,执行栈顶的下一个执行上下文开始执行。
作用域是编译器检测变量是否有声明的地方
作用域链是词法作用域的概念在执行上下文中的体现,JavaScript的作用域是词法作用域,这意味着作用域是由代码在编译时决定的,而不是在运行时决定的。
变量提升
在Javascript中,变量提升是指变量声明被提升到作用域的顶部,这可能会导致一些意想不到的错误,变量提升只有在声明时提升,赋值不会提升。
词法环境
词法环境(Lexical Environment)是一个用来解析变量的词法作用域,它是执行上下文的变量对象,其中包含了所有声明的变量和函数。
词法环境还包括一个指向父词法环境的引用
这个引用允许子词法环境访问父词法环境中的变量,词法环境的作用是确定变量的有效范围和解析变量的引用。
执行上下文与执行栈的关系
执行上下文和执行栈是Javascript中非常重要的两个概念,它们共同控制着Javascript程序的执行,理解这两个概念对于理解Javascript程序的执行非常重要。
理解执行上下文和执行栈
这两个概念对于理解JavaScript程序的执行至关重要,它们是JavaScript中非常重要的两个概念,它们共同控制着JavaScript程序的执行,理解这两个概念对于理解JavaScript程序的执行非常重要。
让我们用一个例子来进一步理解执行上下文和执行栈
function a() {
console.log(b); // undefined
var b = 10;
}
a();
这个例子中,函数a()被调用
当函数a()被调用时,一个新的执行上下文被创建并压入执行栈中,这个执行上下文有两个变量对象,一个是a()函数的变量对象,另一个是全局变量对象。
当控制流到达console.log(b)
执行上下文会先在a()函数的变量对象中查找b变量,如果找不到,则会沿着作用域链向上查找,直到找到全局变量对象中的b变量。
在这个例子中,b变量在全局变量对象中被找到,所以它的值是10,然后控制流到达var b = 10,此时b变量被声明并赋值为10,但由于变量提升,b变量已经存在于a()函数的变量对象中,所以这个赋值实际上是更新了b变量的值。
当函数a()返回时,执行上下文被弹栈
执行栈顶的下一个执行上下文开始执行,这个执行上下文是全局执行上下文,此时b变量的值是10,因此console.log(b)会输出10。
执行上下文和执行栈是JavaScript中非常重要的两个概念
理解这两个概念对于理解JavaScript程序的执行非常重要,它们共同控制着JavaScript程序的执行。