一文详解JavaScript中执行上下文与执行栈「图文结合」

1. 执行上下文(Execution Context)

在JavaScript中,最基本的执行单位是执行上下文(Execution Context)。执行上下文可以理解为一段代码执行时所在的环境,用于存储变量、函数等内存信息,以及确定代码执行的顺序。

在JavaScript中,每当函数被调用时,都会创建一个执行上下文,并且使用执行栈(Execution Stack)来管理这些执行上下文。

一个执行上下文对象包含3个重要属性:变量对象(Variable Object,VO)、作用域链(Scope Chain)和this值,下面分别介绍。

1.1 变量对象(Variable Object)

变量对象是执行上下文中的一个重要属性,它用于存储变量、函数等内存信息。当JavaScript代码执行到一个函数时,会创建一个新的执行上下文,并为该函数创建一个变量对象。

变量对象包括:

函数参数

函数声明

变量声明

其中,函数声明和变量声明都会被提升到当前作用域的顶部,因此在函数内部可以使用变量和函数,即使在声明之前也可以正常使用。

console.log(foo); // undefined

var foo = 'bar';

console.log(foo); // 'bar'

console.log(func); // function func(){...}

func();

function func(){...}

在上面的例子中,变量和函数的声明都被提升到了函数作用域的顶部,因此在声明之前就可以正常使用。

1.2 作用域链(Scope Chain)

作用域链是指一个函数执行时,变量查找的路径,它由函数的活动对象(Activation Object)以及所有父级函数的活动对象组成。

当JavaScript查找一个变量时,先查找当前函数的活动对象,如果找不到就沿着作用域链往上查找,直到全局作用域。如果全局作用域都没找到,就会返回undefined。

var x = 1;

function test() {

var y = 2;

function innerTest() {

var z = 3;

console.log(x, y, z);

}

innerTest();

}

test(); // 1 2 3

在上面的例子中,innerTest函数中的变量z只能在该函数内部访问,变量y只能在innerTest函数的父级函数test中访问,变量x则可以在全局作用域中访问。

1.3 this值

this值是指在函数调用时,所在的执行上下文的一个属性,它代表函数执行的上下文对象。

this值的具体取值,取决于函数的调用方式,通常有以下几种情况:

作为函数调用(函数名()):this指向全局对象(浏览器中为window对象)。

作为方法调用(obj.func()):this指向调用该方法的对象(即方法所在的对象)。

使用apply/call/bind调用:this可以被显式指定。

作为构造函数调用(new构造函数()):this指向新创建的对象。

2. 执行栈(Execution Stack)

执行栈是用于管理JavaScript执行上下文的一种数据结构,它是一个后进先出(LIFO)的栈。

当一个函数被调用时,JavaScript会创建一个新的执行上下文,并将它压入执行栈的栈顶。当函数执行完毕后,它的执行上下文会被弹出执行栈。

function a() {

console.log('a');

b();

}

function b() {

console.log('b');

}

function c() {

console.log('c');

}

a();

c();

在上面的代码中,依次执行了a、b、c三个函数,执行栈的变化如下图所示:

![执行栈示意图](https://img-blog.csdn.net/20171018172058516?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXdlcnR5dHJhbnNwb3J0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/85)

在执行上述代码时,首先执行函数a,而函数a中又调用了函数b,因此函数b被压入执行栈的栈顶。当函数b执行完毕后,它的执行上下文被弹出执行栈,执行上下文回到了函数a中,接着执行函数a中的其他语句。当函数a执行完毕后,它的执行上下文也被弹出执行栈,最后执行函数c中的内容。

3. 总结

执行上下文和执行栈是JavaScript中非常重要的概念,它们决定了JavaScript代码的执行顺序,以及变量、函数的生命周期。

执行上下文包含变量对象、作用域链和this值三个属性,用于存储变量、函数等内存信息,以及确定代码执行的顺序;执行栈则用于管理JavaScript执行上下文的顺序,它是一个后进先出(LIFO)的栈。

深入理解执行上下文和执行栈对于理解JavaScript的运行机制和调试代码非常有帮助,是每个前端工程师必须掌握的知识之一。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。