JavaScript执行上下文和调用栈

编程入门 行业动态 更新时间:2024-10-19 14:43:47

JavaScript执行<a href=https://www.elefans.com/category/jswz/34/1770489.html style=上下文和调用栈"/>

JavaScript执行上下文和调用栈

上节课我们已经说过了,JavaScript的代码执行是发生在js引擎中的调用堆栈的,但是具体是如何运行的,我们来详细剖析一下

如何执行上下文

执行上下文:
执行上下文是指在JavaScript中代码被执行时所创建的环境。它包含了变量、函数、对象和其他代码执行所需的信息。每当函数被调用时,都会创建一个新的执行上下文。
举个例子:
例如要把装披萨的盒子比作执行上下文,披萨比作JavaScript的代码,但是盒子里面可能并不只有披萨,还有餐具和清单!这样才能构建一个吃披萨(执行代码)的环境!

只有一个全局执行上下文(EC)
默认上下文,为不在任何函数内的代码创建(顶级)。

顶级代码示例

声明的变量和声明的函数在全局中使用,所以在顶级代码中就被执行,但是函数内的代码,只有在被调用的时候菜会执行!

执行函数的内部

内部执行上下文

  1. 可变函数
    a. let、const和var声明
    b. 函数
    c. 参数对象

  2. 作用域链
    JavaScript的作用域链是一种用于查找变量和函数的机制。当在代码中引用一个变量时,JavaScript引擎会按照一定的顺序搜索变量的定义。这个搜索过程就是通过作用域链来完成的。
    在JavaScript中,每个函数都有自己的执行上下文,包括一个变量对象(Variable Object),它存储了函数内部定义的变量和函数。当函数被调用时,会创建一个新的执行上下文,并将其添加到作用域链的前端。
    作用域链是一个由多个执行上下文对象组成的链表,它按照函数定义的嵌套关系进行链接。每个执行上下文对象都有一个指向其父级执行上下文对象的引用,这样就形成了一个作用域链。
    当查找一个变量时,JavaScript引擎首先在当前执行上下文的变量对象中查找,如果找到了变量,则使用该变量。如果没有找到,则沿着作用域链向上一级执行上下文的变量对象中查找,直到找到该变量或者到达作用域链的顶端(全局作用域)。
    如果在整个作用域链上都没有找到该变量,则会抛出一个引用错误。
    这种作用域链的机制允许内部函数访问外部函数的变量,即使外部函数已经执行完毕,也仍然可以通过作用域链找到这些变量。这被称为"闭包",是JavaScript中非常强大和有用的特性之一。

  3. this关键字
    "this"关键字在JavaScript中是一个特殊的关键字,它通常用于引用当前执行代码的上下文对象。
    "this"关键字的值在不同的上下文中有不同的含义。它的值取决于函数的调用方式以及函数所属的对象。
    在全局作用域中,"this"引用的是全局对象(在浏览器中是"window"对象,在Node.js中是"global"对象)。
    在函数中,"this"的值取决于函数是如何被调用的。如果函数是作为对象的方法调用的,那么"this"引用的是该对象。如果函数是作为普通函数调用的,那么"this"引用的是全局对象(在浏览器中是"window"对象,在Node.js中是"global"对象)。
    此外,“this"还可以通过一些特殊的函数调用方式来显式地绑定到指定的对象上,例如使用"call”、"apply"或"bind"方法。
    总之,"this"关键字在JavaScript中用于引用当前执行代码的上下文对象,它的值取决于函数的调用方式以及函数所属的对象。

举例说明

函数调用栈

“位置”执行上下文被堆叠在一起以跟踪我们在执行中的位置。

示例

const name = 'Jonas';const first = () => {let a = 1;const b = second(7, 9);a = a + b;return a;
};function second(x, y) {var c = 2;return c;
}const x = first();

首先,让我们逐行解释这段代码的执行过程,以了解函数调用栈的原理是如何应用的:

  1. const name = ‘Jonas’; - 这行代码定义了一个常量name并赋值为字符串’Jonas’。这行代码不涉及函数调用,因此不会影响函数调用栈。在全局代码中就会执行!
  2. const first = () => { … } - 这行代码定义了一个箭头函数first。箭头函数不会立即执行,而是在被调用时才执行。因此,此时不会有函数调用栈的变化。
  3. function second(x, y) { … } - 这行代码定义了一个名为second的函数。函数定义本身不会改变函数调用栈,只有在函数被调用时才会推入调用栈。
  4. const x = first(); - 这行代码调用了函数first并将其返回值赋给常量x。函数调用会改变函数调用栈的状态。
    现在我们来分析函数调用栈的变化:
  5. const x = first(); - 这行代码调用了函数first,将其推入函数调用栈的顶部。
  6. const b = second(7, 9); - 在函数first中,调用了函数second,将其推入函数调用栈的顶部。
  7. return c; - 函数second执行完毕,将其执行结果返回给调用者first。
  8. a = a + b; - 在函数first中,将变量b的值加到变量a上。
  9. return a; - 函数first执行完毕,将其执行结果返回给调用者。
  10. const x = first(); - 函数调用栈中只剩下全局上下文,函数调用栈为空。
    最终,常量x的值为3,因为函数first的执行结果是3。
    这个例子展示了函数调用栈的典型行为:当一个函数被调用时,它的执行上下文被推入调用栈的顶部,函数执行完毕后,它的执行上下文从调用栈中弹出,控制权返回给调用者。这个过程会一直重复,直到所有函数执行完毕,调用栈为空。

更多推荐

JavaScript执行上下文和调用栈

本文发布于:2023-11-16 17:31:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1630289.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:上下文   JavaScript

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!