JavaScript 之 作用域变量提升闭包

一、JavaScript 代码的执行

  • 浏览器内核是由两部分组成的,以 webkit 为例
    • WebCore:负责HTML解析、布局、渲染等等相关的工作
    • JavaScriptCore:解析、执行 JavaScript 代码
  • 另外一个强大的 JavaScript 引擎就是 V8 引擎

二、深入 V8 引擎原理

  • V8 是用 C ++ 编写的 Google 开源高性能 JavaScript 和 WebAssembly (未来 js 替代)引擎,它用于 Chrome 和 Node.js
    • 跨平台
  • 它实现 ECMAScriptWebAssembly ,并在 Windows 7 或更高版本,macOS 10.12+ 和使用 x64,IA-32,ARM 或 MIPS 处理器的 Linux 系统上运行
  • V8 可以独立运行,也可以嵌入到任何 C ++ 应用程序
  • 步骤
    • 高级语言转化成二进制代码
      • 抽象语法树
        • 知道整个代码的结构
      • 字节码
        • 类似于汇编代码
        • 跨平台
          • mac os
          • java:一次编写,到处运行
            • 需要安装并依赖于 java 虚拟机
      • 优化的机器码
        • 尽量保证传入的参数的类型一致
        • ts 能够提高代码性能
    • lgnition:AST 转化为字节码
    • TurboFan

三、V8 引擎的架构

  • 浏览器中存在渲染引擎,v8 是专门用于处理 js 代码的一部分

  • Scanner 进行扫描,进行词法分析

  • V8 引擎本身的源码非常复杂,大概有超过100w行C++代码

  • Parser 模块将 JavaScript 代码转换成 AST(抽象语法树)

    • 进行语法分析

    • 预解析(声明时候没有进行调用,被认为是不被执行的代码,进行预解析,后面执行的话就会进行全量解析) =》 全量解析(函数立即执行,只进行一次全量解析)

      • 避免函数嵌套
    • 解释器并不直接认识 JavaScript 代码

    • 如果函数没有被调用,那么是不会被转换成 AST 的

  • Ignition 是一个解释器,会将 AST 转换成 ByteCode(字节码)

    • 会收集 TurboFan 优化所需要的信息(比如函数参数的类型信息,有了类型才能进行真实的运算)
    • 如果函数只调用一次,Ignition会解释执行ByteCode
  • TurboFan是一个编译器,可以将 字节码 编译为 CPU 可以 直接执行的机器码

    • 如果一个函数被多次调用,会被标记为热点函数,那么就会经过 TurboFan 转换成优化的机器码,提高代码的执行性能
    • 但是,机器码实际上也会被还原为 ByteCode
      • 如果后续执行函数的过程中,类型发生了变化(比如sum函数原来执行的是number类型,后来执行变成了string类型)
      • 之前优化的机器码并不能正确的处理运算,就会逆向的转换成字节码
  • 词法分析(对一条语句进行此法分析,提取出关键字)=》 语法分析(解析成 js 中对应的语法,生成对应的 AST 树

image.png

四、初始化全局对象

  • js 引擎会在执行代码之前,会在堆内存中创建一个全局对象:Global Object(GO)
    • 该对象 所有的作用域(scope)都可以访问
    • 里面会包含 Date、Array、String、Number、setTimeout、setInterval 等等
    • 其中还有一个 window 属性指向自己

五、执行上下文

  • js 引擎内部有一个执行上下文栈(Execution Context Stack,简称 ECS),它是用于执行代码的调用栈
    • 执行的是全局的代码块
      • 全局的代码块为了执行会构建一个 全局执行上下文 Global Execution Context(GEC)
      • GEC 会被放入到 执行上下文栈 ECS 中执行
  • GEC 被放入到 ECS 中里面包含两部分内容
    • 第一部分:变量的作用域提升:在代码执行前,在 parser 转成 AST 的过程中,会将全局定义的变量、函数等加入到 GlobalObject 中,但是并不会赋值
    • **第二部分:**在代码执行中,对变量赋值,或者执行其他的函数

六、VO 对象

  • 每一个执行上下文会关联一个 VO(Variable Object,变量对象),变量和函数声明会被添加到这个 VO 对象中
  • 全局代码被执行的时候,VO 就是 GO 对象
  • 全局对象就是 window 对象,this
  • 作用域链

七、函数执行

  • 在执行的过程中执行到一个函数时,就会根据函数体创建一个函数执行上下文(Functional Execution Context,简称 FEC),并且压入到 EC Stack
  • 每个执行上下文都会关联一个 VO,函数执行上下文关联的 VO 是什么
    • 当进入一个函数执行上下文时,会在堆内存中创建一个 AO 对象(Activation Object)
    • 这个 AO 对象会使用 arguments 作为初始化,并且初始值是传入的参数
    • 这个 AO 对象会作为执行上下文的 VO 来存放变量的初始化(都是 undefined)
  • 执行完后就销毁
  • 只有是函数的时候才会指向一个地址,其他都是 undefined
    • 创建 obj 对象(刚开始也是 undefined )
  • 函数多层嵌套,并不会把所有的对象都创建出来,只会创建第一个

八、JavaScript 的代码的执行流程

  • 首先在执行前会现在堆内存中开辟一块空间 (GO) 存放一些初始的值 如 Number String等等
  • 还有代码中定义的一些变量 函数(在 parser 转成 AST 树的过程中存放在 GO 中的 )并没有赋值
  • 同时在执行代码时在执行上下文栈(ECS)中存放一个全局执行上下文(GEC) 用于执行代码
    • GO中对应的函数 也会在堆内存中开辟出空间 为 Function Object 初始一些数据(name length scope chain等)
  • 开始执行代码
  • 每个EC中有着三个重要的内容(VO scope chain 以及this)
  • VO指向对应的作用域(全局作用域(GO) 函数作用域(AO))
1. 基本数据类型是按值进行操作
2. 基本数据类型是存放在栈区的
3. 无论当前看到的栈内存还是引用数据类型会使用的堆内存都属于计算机内存
4. GO 

九、作用域和作用域链

  • 当进入到一个执行上下文时,执行上下文也会关联一个作用域链Scope Chain
    • 作用域链是一个对象列表,用于变量标识符的求值
    • 当进入一个执行上下文时,这个作用域链被创建,并且根据代码类型,添加一系列的对象
  • 代码类型
    • 全局代码
    • 函数代码
  • 函数被创建的时候,作用域链已经确定了
    • 因此可以画出

十、GO/AO/VO以及作用域和作用域链

  • GO

    • Global Object JS代码在执行前会现在堆内存中创建一个全局对象(GO)
    • 有自己的地址,可以对其进行访问
    • 用于存放一些定义好的变量方法等
    • 包含 Date Array String Number setTimeout等
    • 同时有一个 window 属性指向自己
    • 同时在语法分析转成 AST 的过程中也会将一些变量 函数 存放在 GO 中 只是变量的初始值为 undefined
  • AO

    • 函数在执行前会先在堆内存中创建一个AO(Activation Object)对象 里面存放这arguments 对应函数的形参 以及在函数中定义的变量 初始值为 undefined
  • VO

    • Variable Object 在执行函数时 会在执行上下文栈(ECS)中进入一个函数执行上下文(FEC)其中有三个核心
    • 核心之一是VO 指向的是该函数在内存中解析时创建的AO 而在全局执行上下文中指向的是GO
  • 作用域,作用域链

    • 当进入到一个执行上下文时 执行上下文会关联一个作用域链
    • 通常作用域链在解析时就被确定,因此,作用域链域函数的定义位置有关,而与它的调用位置无关

十一、面试题

    // 1.面试题一:// var n = 100// function foo() {//   n = 200 //直接访问上一层的 n // }// foo()// console.log(n)//200// 2.面试题二:// var n = 100// function foo() {//   console.log(n)//   var n = 200//   console.log(n)// }// foo()//undefined  200// 3.面试题三:// var n = 100// function foo1() {//   console.log(n)// }// function foo2() {//   var n = 200//   console.log(n)//   foo1()// }// foo2() //200 100// 4.面试题四:// var n = 100// function foo() {//   console.log(n)//   return//执行// 解析的时候//   var n = 200  //还是会在里面定义n:undefined// }// foo()// 5.在开发中可能会出现这样错误的写法// function foo() {//   message = "Hello World"//就是当成 全局变量 进行解析,没有 var// }// foo()// console.log(message)// 6.面试题五:function foo() {var a = b = 100}foo()console.log(a)//访问不到,报错console.log(b)//当成全局变量 100

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/650690.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java面向对象三大特征之多态

在之前的文章,我们分别介绍了类与对象、面向对象三大特征的封装、以及继承(一)、继承(二)。这一篇文章,我们介绍Java面向对象三大特征的最后一个——多态。 多态 多态的概述 概念:完成某个行为…

前端工程化之:webpack1-1(构建工具)

一、浏览器端的模块化 1.问题 效率问题:精细的模块划分带来了更多的 JS 文件,更多的 JS 文件带来了更多的请求,降低了页面访问效率;兼容性问题:浏览器目前仅支持 ES6 的模块化标准,并且还存在兼容性问题&…

Hive之set参数大全-17

配置是否启用 HiveServer2 的 Web 用户界面(WebUI)中的跨源资源共享(CORS) 在 Hive 中,hive.server2.webui.enable.cors 是一个参数,用于配置是否启用 HiveServer2 的 Web 用户界面(WebUI&…

CVE-2024-23897 Jenkins 任意文件读取漏洞

项目介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件项目可以进行持续集成。Jenkins是开源CI&CD软件领导者, 提供超过1000个插…

Java集合相关面试题

📕作者简介: 过去日记,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。 📗本文收录于java面试题系列,大家有兴趣的可以看一看 📘相关专栏Rust初阶教程、go语言基…

C# 设置一个定时器函数

C#中,创建设置一个定时器,能够定时中断执行特定操作,可以用于发送心跳、正计时和倒计时等。 本文对C#的定时器简单封装一下,哎,以方便定时器的创建。 定义 using Timer System.Timers.Timer;class SetTimer {Timer …

Nacos注册中心:揭秘分布式系统的灵魂之所

目录 一、Nacos注册中心简介 1.1 概述 1.2 作用和意义 二、Nacos的特点和优势

OSPF协议基础(OSPF工作过程)

目录 OSPF基本工作原理邻居建立过程Router ID发现并建立邻居 - Hello报文OSPF邻居建立过程 链路状态信息丰富的数据链路层支持能力网络类型 - P2P网络网络类型 - 广播型网络网络类型 - NBMA网络网络类型 - P2MP网络OSPF的度量方式 报文类型及作用OSPF协议报文头部OSPF报文类型O…

物理服务器

物理服务器 物理服务器是一种独立的、非虚拟化的计算机设备,它通常被用作高性能应用、数据库、存储和网络等关键业务应用的运行平台。物理服务器可以提供更高的处理能力、更好的安全性和可靠性,但需要用户自行维护和管理。 物理服务器的形式多种多样&…

图论-寒假

文章目录 A - Amusement Arcade题意:题解:代码: B - Brexiting and Brentering题意:题解:代码: I - Montys Hall题意:题解:代码: A - Amusement Arcade 题意&#xff1a…

每日一道编程题:回文数

题目 一串字符如果从左读和从右读完全相同&#xff0c;我们称之为回文。请判断键盘输入一串字符&#xff08;不超过1000位&#xff09;&#xff0c;是否是回文。是&#xff0c;则输出YES&#xff0c;否则输出NO。 输入样例 1aabbccbbaa1输出样例 YES代码 #include <bit…

k8s-调度

调度 从上面的架构图我们可以看到,调度是工作在Master,负责调度Pod&#xff0c;为POD分配Node。 调度的工作原理 #查看所有的Node kubectl get nodes 我们可以看到节点有一个Name,这就是调度的关键。 调度的步骤&#xff1a; 1 创建POD的时候每一个POD都会有一个叫NodeName的…

老板为何都对项目经理毕恭毕敬!因为这个职位一念成佛一念成魔

hello宝子们...我们是艾斯视觉擅长ui设计和前端开发10年经验&#xff01;希望我的分享能帮助到您&#xff01;如需帮助可以评论关注私信我们一起探讨&#xff01;致敬感谢感恩&#xff01; 老板为何都对项目经理毕恭毕敬&#xff01;因为这个职位一念成佛一念成魔 曾几何时&am…

Linux:命名管道及其实现原理

文章目录 命名管道指令级命名管道代码级命名管道 本篇要引入的内容是命名管道 命名管道 前面的总结中已经搞定了匿名管道&#xff0c;但是匿名管道有一个很严重的问题&#xff0c;它只允许具有血缘关系的进程进行通信&#xff0c;那如果是两个不相关的进程进行通信&#xff0…

【最佳实践】Go 组合模式对业务解耦

在 Go 语言中&#xff0c;组合模式&#xff08;Composition&#xff09;是通过嵌入结构体&#xff08;embedding structs&#xff09;来实现的。它允许我们构建复杂的对象&#xff0c;通过将简单对象组合成树形结构来表示整个部分的层次结构。在 Go 中&#xff0c;这种模式不仅…

《佛法修学概要》009-012集研讨

课程摘要 9、只有走出心中的妄想&#xff0c;才可能接觸彌陀的光明&#xff01; 佛陀在經典裡講出一個譬喻&#xff0c;說有一座動物園&#xff0c;這座動物園關了很多動物。其中有一隻袋鼠&#xff0c;就是澳洲那種很會跳的袋鼠。動物園的管理員&#xff0c;給牠圈了一個十公尺…

《合成孔径雷达成像算法与实现》Figure5.16

clc clear close all距离向参数 R_eta_c 20e3; % 景中心斜距 Tr 25e-6; % 发射脉冲时宽 Kr 0.25e12; % 距离向调频率 Fr 7.5e6; % 距离向采样率 Nrg 256; % 距离线采样点数 Bw abs(Kr*Tr); …

uniapp+极光做消息推送

借鉴地址uniapp极光做消息推送_uniapp 极光 配置 ios 自定义消息-CSDN博客

【vue oidc-client】invalid_requestRequest Id: 0HN0OOPFRLSF2:00000002

需求&#xff1a;完成统一登录&#xff0c;需要从三方平台跳到我们的平台。 oidc-client报错记录。这个一般是配置信息出错&#xff0c;需要和三方平台进行沟通&#xff0c;一定要把client_id&#xff0c;密钥进行对应&#xff1b; 同时关于此次出错还修改了以下代码&#xff…

Python 办公自动化主要Excel,PPT,Word,邮件,再加上数据分析、爬虫等

python办公自动化 Python 办公自动化主要Excel&#xff0c;PPT&#xff0c;Word&#xff0c;邮件&#xff0c;再加上数据分析、爬虫等技能#####Excel自动化 pip install xlwings pip install openpyxl 实现对Excel表格的读、写、格式调整、自动化图表生成等 以下用xlwings进行…