【进阶1-1期】理解JavaScript 中的执行上下文和执行栈

news/2023/12/1 11:42:59 标签: javascript, 前端, 面试

(关注福利,关注本公众号回复[资料]领取优质前端视频,包括Vue、React、Node源码和实战、面试指导)

本周正式开始前端进阶的第一期,本周的主题是调用堆栈,,今天是第一天

本计划一共28期,每期重点攻克一个面试重难点,如果你还不了解本进阶计划,点击查看前端进阶的破冰之旅

本期推荐文章

理解JavaScript 中的执行上下文和执行栈,由于微信不能访问外链,点击阅读原文就可以啦。

推荐理由

首先这是一篇译文,文章翻译的挺好,详细介绍了执行上下文的类型和创建过程,对于理解JS运行机制有极大的帮助,特别是从另一个角度介绍了ES5/6情况下变量提升的情况和原因。

阅读笔记

执行上下文是当前 JavaScript 代码被解析和执行时所在环境的抽象概念。

执行上下文的类型

执行上下文总共有三种类型

  • 全局执行上下文:只有一个,浏览器中的全局对象就是 window 对象,this 指向这个全局对象。
  • 函数执行上下文:存在无数个,只有在函数被调用的时候才会被创建,每次调用函数都会创建一个新的执行上下文。
  • Eval 函数执行上下文: 指的是运行在 eval 函数中的代码,很少用而且不建议使用。

执行栈

执行栈,也叫调用栈,具有 LIFO(后进先出)结构,用于存储在代码执行期间创建的所有执行上下文。

首次运行JS代码时,会创建一个全局执行上下文并Push到当前的执行栈中。每当发生函数调用,引擎都会为该函数创建一个新的函数执行上下文并Push到当前执行栈的栈顶。

根据执行栈LIFO规则,当栈顶函数运行完成后,其对应的函数执行上下文将会从执行栈中Pop出,上下文控制权将移到当前执行栈的下一个执行上下文。

执行上下文的创建

执行上下文分两个阶段创建:1)创建阶段; 2)执行阶段

创建阶段

  • 1、确定 this 的值,也被称为 This Binding
  • 2、LexicalEnvironment(词法环境) 组件被创建。
  • 3、VariableEnvironment(变量环境) 组件被创建。

直接看伪代码可能更加直观

ExecutionContext = {  
  ThisBinding = <this value>,     // 确定this 
  LexicalEnvironment = { ... },   // 词法环境
  VariableEnvironment = { ... },  // 变量环境
}
This Binding
  • 全局执行上下文中,this 的值指向全局对象,在浏览器中this 的值指向 window 对象,而在nodejs中指向这个文件的module对象。
  • 函数执行上下文中,this 的值取决于函数的调用方式。具体有:默认绑定、隐式绑定、显式绑定(硬绑定)、new绑定、箭头函数,具体内容会在【this全面解析】部分详解。
词法环境(Lexical Environment)

词法环境有两个组成部分

  • 1、环境记录:存储变量和函数声明的实际位置
  • 2、对外部环境的引用:可以访问其外部词法环境

词法环境有两种类型

  • 1、全局环境:是一个没有外部环境的词法环境,其外部环境引用为 null。拥有一个全局对象(window 对象)及其关联的方法和属性(例如数组方法)以及任何用户自定义的全局变量,this 的值指向这个全局对象。
  • 2、函数环境:用户在函数中定义的变量被存储在环境记录中,包含了arguments 对象。对外部环境的引用可以是全局环境,也可以是包含内部函数的外部函数环境。

直接看伪代码可能更加直观

GlobalExectionContext = {  // 全局执行上下文
  LexicalEnvironment: {          // 词法环境
    EnvironmentRecord: {           // 环境记录
      Type: "Object",                 // 全局环境
      // 标识符绑定在这里 
      outer: <null>                    // 对外部环境的引用
  }  
}

FunctionExectionContext = { // 函数执行上下文
  LexicalEnvironment: {        // 词法环境
    EnvironmentRecord: {          // 环境记录
      Type: "Declarative",         // 函数环境
      // 标识符绑定在这里               // 对外部环境的引用
      outer: <Global or outer function environment reference>  
  }  
}
变量环境

变量环境也是一个词法环境,因此它具有上面定义的词法环境的所有属性。

在 ES6 中,词法 环境和 变量 环境的区别在于前者用于存储函数声明和变量( letconst绑定,而后者仅用于存储变量( var绑定。

使用例子进行介绍

let a = 20;  
const b = 30;  
var c;

function multiply(e, f) {  
 var g = 20;  
 return e * f * g;  
}

c = multiply(20, 30);

执行上下文如下所示

GlobalExectionContext = {

  ThisBinding: <Global Object>,

  LexicalEnvironment: {  
    EnvironmentRecord: {  
      Type: "Object",  
      // 标识符绑定在这里  
      a: < uninitialized >,  
      b: < uninitialized >,  
      multiply: < func >  
    }  
    outer: <null>  
  },

  VariableEnvironment: {  
    EnvironmentRecord: {  
      Type: "Object",  
      // 标识符绑定在这里  
      c: undefined,  
    }  
    outer: <null>  
  }  
}

FunctionExectionContext = {  
   
  ThisBinding: <Global Object>,

  LexicalEnvironment: {  
    EnvironmentRecord: {  
      Type: "Declarative",  
      // 标识符绑定在这里  
      Arguments: {0: 20, 1: 30, length: 2},  
    },  
    outer: <GlobalLexicalEnvironment>  
  },

  VariableEnvironment: {  
    EnvironmentRecord: {  
      Type: "Declarative",  
      // 标识符绑定在这里  
      g: undefined  
    },  
    outer: <GlobalLexicalEnvironment>  
  }  
}

变量提升的原因:在创建阶段,函数声明存储在环境中,而变量会被设置为 undefined(在 var 的情况下)或保持未初始化(在 letconst 的情况下)。所以这就是为什么可以在声明之前访问 var 定义的变量(尽管是 undefined ),但如果在声明之前访问 letconst 定义的变量就会提示引用错误的原因。这就是所谓的变量提升。

执行阶段

此阶段,完成对所有变量的分配,最后执行代码。

如果 Javascript 引擎在源代码中声明的实际位置找不到 let 变量的值,那么将为其分配 undefined 值。

参考

理解 Javascript 执行上下文和执行栈

往期文章查看

  • 【进阶1-1期】理解JavaScript 中的执行上下文和执行栈
  • 【进阶1-2期】JavaScript深入之执行上下文栈和变量对象
  • 【进阶1-3期】JavaScript深入之内存空间详细图解
  • 【进阶1-4期】JavaScript深入之带你走进内存机制制
  • 【进阶1-5期】JavaScript深入之4类常见内存泄漏及如何避免
  • 【进阶2-1期】深入浅出图解作用域链和闭包

每周计划安排

每周面试重难点计划如下,如有修改会通知大家。每周一期,为期半年,准备明年跳槽的小伙伴们可以把本公众号置顶了。

  • 【进阶1期】 调用堆栈
  • 【进阶2期】 作用域闭包
  • 【进阶3期】 this全面解析
  • 【进阶4期】 深浅拷贝原理
  • 【进阶5期】 原型Prototype
  • 【进阶6期】 高阶函数
  • 【进阶7期】 事件机制
  • 【进阶8期】 Event Loop原理
  • 【进阶9期】 Promise原理
  • 【进阶10期】Async/Await原理
  • 【进阶11期】防抖/节流原理
  • 【进阶12期】模块化详解
  • 【进阶13期】ES6重难点
  • 【进阶14期】计算机网络概述
  • 【进阶15期】浏览器渲染原理
  • 【进阶16期】webpack配置
  • 【进阶17期】webpack原理
  • 【进阶18期】前端监控
  • 【进阶19期】跨域和安全
  • 【进阶20期】性能优化
  • 【进阶21期】VirtualDom原理
  • 【进阶22期】Diff算法
  • 【进阶23期】MVVM双向绑定
  • 【进阶24期】Vuex原理
  • 【进阶25期】Redux原理
  • 【进阶26期】路由原理
  • 【进阶27期】VueRouter源码解析
  • 【进阶28期】ReactRouter源码解析

交流

本人Github链接如下,欢迎各位Star

http://github.com/yygmind/blog

我是木易杨,网易高级前端工程师,跟着我每周重点攻克一个前端面试重难点。接下来让我带你走进高级前端的世界,在进阶的路上,共勉!

如果你想加群讨论每期面试知识点,公众号回复[加群]即可


http://www.niftyadmin.cn/n/1693601.html

相关文章

spark+hbase+kafka+zookeeper集群一条龙搭建教程

spark集群是依赖hadoop的。 hadoop集群搭建教程&#xff1a; Hadoop集群搭建教程&#xff08;一&#xff09; Hadoop集群搭建教程&#xff08;二&#xff09; Spark集群 集群部署 官网下载&#xff1a;spark官网 这里要注意spark兼容的hadoop版本 接着解压&#xff1a; tar…

爬取qq号

import reimport urllib.requestimport osimport jsonimport sslfrom collections import deque#把爬去的数据保存到文件的函数def writeFileBytes(htmlBytes,toPath): with open(toPath,"wb") as f: f.write(htmlBytes)def writeFileStr(htmlBytes,toPath): with op…

死磕java concurrent包系列(一)从乐观锁、悲观锁到AtomicInteger的CAS算法

前言Java中有各式各样的锁&#xff0c;主流的锁和概念如下&#xff1a;这篇文章主要是为了让大家通过乐观锁和悲观锁出发&#xff0c;理解CAS算法&#xff0c;因为CAS是整个Concurrent包的基础。乐观锁和悲观锁首先&#xff0c;java和数据库中都有这种概念&#xff0c;他只是一…

maven打包--同时将仓库依赖和本地依赖的jar包也打进去

目录maven添加依赖maven添加本地依赖项目打包maven打包将依赖包一同打进去将本地依赖包也一同打包可能出现的问题依赖包不与项目代码一同编译maven添加依赖 首先&#xff0c;如何在maven项目中添加依赖包&#xff1f;这个相信对于大部分人来说是非常简单的&#xff0c;在pom.x…

核密度估计原理及sparkpython实现

核密度估计属于非参数估计&#xff0c;它主要解决的问题就是在对总体样本的分布未知的情况&#xff0c;如何估计样本的概率分布。 像平时&#xff0c;我们经常也会用直方图来展示样本数据的分布情况&#xff0c;如下图&#xff1a; 但是&#xff0c;直方图有着明显的缺点&…

深度学习中的注意力机制(Attention)

注意力模型最近几年在深度学习各个领域被广泛使用&#xff0c;无论是图像处理、语音识别还是自然语言处理的各种不同类型的任务中&#xff0c;都很容易遇到注意力模型的身影。所以&#xff0c;了解注意力机制的工作原理对于关注深度学习技术发展的技术人员来说有很大的必要。 …

揭秘天猫双11背后:20万商家600万张海报,竟然全靠他......

还记得去年双11&#xff0c;秋裤厂商带着“五彩斑斓的黑”需求找设计师的故事吗&#xff1f; 现在&#xff0c;已经有超过20万客户把这个AI设计师鹿班带回家。 今年&#xff0c;鹿班除了为天猫淘宝平台提供服务之外&#xff0c;还通过阿里云全面为各行业客户输出AI设计能力。20…

C++ ifndef /define/ endif 作用和用法

ifndef/define/endif”主要目的是防止头文件的重复包含和编译   比如你有两个C文件&#xff0c;这两个C文件都include了同一个头文件。而编译时&#xff0c;这两个C文件要一同编译成一个可运行文件&#xff0c;于是问题来了&#xff0c;大量的声明冲突。 还是把头文件的内容都…

GO基础深入总结

2019独角兽企业重金招聘Python工程师标准>>> GO的关键字&#xff1a; 包管理&#xff1a;package、import 变量&#xff1a;var、map、struct、interface、const、type 函数&#xff1a;func、return、defer 循环&#xff1a;if、else、switch、case、fallthought、…

WebapiTestClient 是一款用于API开发的NuGet包 以文档形式展现 使用方法如下

注意事项&#xff1a; 创建标准版的API 另外 创建之后要将javascript文件中的所有jquery.js版本删除掉 只留一个1.10.2版本 1、安装NuGet包 WebapiTestClient 2、在API层 右键》属性》生成》输出路径、勾选XML文档文件 复制后面的路径 3、找到API项目下的Areas/HelpPa…

EventBus的初级使用--Activity间传递消息

2019独角兽企业重金招聘Python工程师标准>>> Activity 间的数据通信&#xff0c;对于数据量比较大的&#xff0c;避免使用 Intent Parcelable 的方式&#xff0c;可以考虑 EventBus 等替代方案&#xff0c;以免造成 TransactionTooLargeException。 EventBus是一款…

第1篇-对蓝鲸运维的个人理解

先介绍蓝鲸是什么&#xff1f; 蓝鲸智云&#xff0c;简称蓝鲸&#xff0c;是一套基于PaaS的技术解决方案&#xff1b;通过蓝鲸&#xff0c;可以实现&#xff1a;1、“运维基础服务”的无人值守&#xff1b;运维基础服务就是我们经常做的发布变更和故障处理&#xff0c;日常的运…

新版本vscode使用配置文件功能,解决不同项目使用不同的插件

如果你同时有vue2,vue3的项目。一定会遇到插件的问题。因为vue2项目插件是使用vetur的&#xff0c;vue3是使用volar的。 以前vscode为了在不同项目中能使用不同的配置文件&#xff0c;是使用工作区的概念去解决的&#xff0c;但是比较复杂而且不好用。 现在新版本的vscode&…

Koa 使用小技巧

cookie的安全保护基于cookie来验证用户状态的系统中&#xff0c;如何提高cookie的安全级别是首要因素&#xff0c;最简单直接的方式就生成的cookie值随机而且复杂。一般使用uuid来生成cookie&#xff0c;生成的随机串在复杂度上已满足需求&#xff0c;但是如果真被攻击者尝试到…

通俗易懂,JDK 并发容器总结

该文已加入开源项目&#xff1a;JavaGuide&#xff08;一份涵盖大部分Java程序员所需要掌握的核心知识的文档类项目&#xff0c;Star 数接近 14 k&#xff09;。地址:https://github.com/Snailclimb... 一 JDK 提供的并发容器总结 实战Java高并发程序设计》为我们总结了下面几种…

11月技术考核:LINUX系统重新安装

1.Linux系统原有分区/data 有数据&#xff0c;再不格式化/data分区的情况下重装系统首先在一台有/data分区的服务器系统&#xff0c;查看一下该分区的大小。可以看到该空间为9.8g&#xff0c;然后在看一下该目录下的文件。确认好之后开始重装系统。从光盘引导镜像进入安装流程。…
最新文章