JS是怎样执行的

JS是怎样执行的

问:请你快速说出JS有哪些标签:
答:单线程、脚本语言、操作DOM吧啦吧啦……
问:好,那你知道JS的执行过程吗?
答:……-_-||


疑问

以前就在想,为什么java需要编译,js就不需要呢?原来编程语言分为静态语言和动态语言:

静态语言:比如C++、Go等,都需要提前编译 (AOT) 成机器码然后执行,这个过程主要使用编译器来完成;
动态语言:比如JavaScript、Python等,只在运行时进行编译执行 (JIT) ,这个过程通过解释器完成;

v8执行js过程

一、【解析器】Parser生成抽象语法树(AST)

在Chrome中开始下载Javascript文件后,Parser就会开始并行在单独的线程上解析代码。生成AST的过程可以分为词义分析和语义分析两个过程。

1、词法分析

主要是将字符流(char stream) 转换成标记流(token stream),字符流就是我们一行一行的代码,token是指语法上不能再分的、最小的单个字符或者字符串。

为了要详细看到token stream,我使用了recast 来模拟浏览器解析JS。

安装esprima

npm i  recast --save

新建文件 recast.js

const recast = require("recast");const code = 'const LK = 1';const ast = recast.parse(code);console.log(ast);

执行node recast.js

node recast.js

我截取了tokens对象,可以看到JS代码被切割为type、value的键值对。

2、语义分析

语义分析的目的是将分词得到的语法单元进行一个整体的组合,分析确定语法单元之间的关系。简单来说,语义分析可以理解成对语句(statement)和表达式(expression)的识别。语义分析是一个递归的过程,所以它会将分词分析出来的数组转化成树形的表达形式(这就是AST中T的由来)。同时,会验证语法,语法如果存在错误的话,会抛出语法错误。

可以看到,短短一句JS代码就被解析为树状的JSON,各位看官可在https://esprima.org/demo/parse.html在线转AST。

二、【解释器】Ignition生成字节码

字节码是机器码的抽象,可以看作是小型的构建块,这些构建块组合到一起构成任何JavaScript功能。字节码比机器码占用更小的内存,这也是为什么V8使用字节码的一个很重要的原因。字节码不能够直接在处理器上运行,需要通过解释器将其转换为机器码后才能执行。

通过上图可以看出,Ignition把前一步得到的AST通过字节码生成器经过一些列的优化生成字节码。 在这个过程中:

  • Register Optimizer: 主要是避免寄存器不必要的加载和存储;
  • Peephole Optimizer: 寻找直接码中可以复用的部分,并进行合并;
  • Dead-code Elimination: 删除无用的代码,减少字节码的大小;

三、【编译器】TurboFan

Ignition执行上一步生成的字节码,并记录代码运行的次数等信息,如果同一段代码执行了很多次,就会被标记为 “HotSpot”(热点代码),然后把这段代码发送给 编译器TurboFan,然后TurboFan把它编译为更高效的机器码储存起来,等到下次再执行到这段代码时,就会用现在的机器码替换原来的字节码进行执行,这样大大提升了代码的执行效率。 另外,当TurboFan判断一段代码不再为热点代码的时候,会执行去优化的过程,把优化的机器码丢掉,然后执行过程回到Ignition

从V8的解析、解释、编译过程去提高js代码性能

一、解析过程

  • 删除多余的代码。
    减少浏览器请求js文件时间,减少解析过程及后续流程时间。
  • 延迟加载不必要的js【优化首屏加载】。
    避免加载和编译那些会延迟页面初始显示的 JavaScript 代码,页面完全加载后,我们可以再开始加载这些功能,以便它们在用户开始交互时立即可用,Google 建议将此延迟加载以 50 毫秒为单位进行,这样就不会影响用户与页面的交互。
  • 正确的书写js代码。
    减少语义分析抛出问题成本。

二、解释过程

V8采用JIT模式编译,JIT必须是强类型语言,编译在执行之前,编译直接生成CPU能够执行的二进制文件,执行时CPU不需要做任何编译操作,直接执行,性能最佳。

  • 声明变量时提供默认类型,加快JIT介入。
  • 不要轻易改变变量的类型,否则提高编译时的类型处理成本。

三、编译过程

  • 始终使用计算复杂度最低的算法和最佳的数据结构来解决任务。

  • 重写算法以获得相同的结果和更少的计算。

  • 避免递归调用。

  • 给重复的函数加入变量、计算和调用。

  • 分解和简化数学公式。

  • 使用搜索数组:用它们来获取基于另一个的值,而不是使用 switch/case 语句。

  • 使条件总是更有可能为真,以更好地利用处理器的推测执行。

  • 如果可以,请使用位级运算符替换某些操作,因为这些运算符的处理周期较短。

AST应用

一、babel

babel是一个javascript编译器,用来将es6语法编译成es5。

1、解析

通过解析器babylon将代码解析成抽象语法树。

2、解析

通过babel-traverse plugin对抽象语法树进行深度优先遍历,遇到需要转换的,就直接在AST对象上对节点进行添加、更新及移除操作,比如遇到箭头函数,就转换成普通函数,最后得到新的AST树。

3、生成(Generate)

通过babel-generator将AST树生成es5代码。

二、vue模板编译过程

Vue 提供了 2 个版本,一个是 Runtime + Compiler ,另一个是 Runtime only 的,前者是包含编译代码的,会把编译的过程放在运行时做,后者是不包含编译代码的,需要借助 webpack 的vue-loader把模板编译render函数。不管使用哪个版本,都有一个环节,就是将模板编译成render函数。

1、解析

将模板字符串解析生成 AST,这里的解析器是vue自己实现的,解析过程中会使用正则表达式对模板顺序解析,当解析到开始标签、闭合标签、文本的时候都会有相对应的回调函数执行,来达到构造 AST 树的目的。

2、解析

vue模板中并不是所有数据都是响应式的,有很多数据是首次渲染后就永远不会变化的,那么这部分数据生成的 DOM 也不会变化,我们可以在patch的过程跳过对他们的比对。
此阶段会深度遍历生成的 AST树,检测它的每一颗子树是不是静态节点,如果是静态节点则它们生成 DOM 永远不需要改变,这对运行时对模板的更新起到极大的优化作用。

3、生成(Generate)

通过generate方法,将ast生成render函数。

参考链接:juejin.im/post/5debce…

原文链接:juejin.im

上一篇:JavaScript实现康威生命游戏
下一篇:React开发日记-React Hook/Mobx 数据状态管理对比

相关推荐

  • 🙋Hanjst汉吉斯特改进+enSafeExpression安全表达式等

    Hanjst汉吉斯特模版语言及模版引擎,近期持续改进升级。 这次改进主要是增加了对安全输出表达式兼容,由于涉及到对软件开发过程中的效率和软件运行效率的平衡和取舍,所以多写了几句,以描述这个权衡利弊对...

    3 个月前
  • 🙋Hanjst汉吉斯特升级:+showImageAsync及性能改进等

    自2019年元旦🙋Hanjst汉吉斯特 模板语言及其编译引擎发布,已经过去一年多了。 这期间随着 🙋Hanjst汉吉斯特 的推广应用,我们也陆续发布了如下一些更新内容: 🛠️Hanjst/汉吉...

    4 个月前
  • 🙋Hanjst汉吉斯特优化+JsonDataFromScript等

    近日继续对 🙋Hanjst汉吉斯特优化改进。这次的改进思考是从服务器端返回的 HanjstJsonData的容器设计问题。目前的做法是服务器端的HanjstJsonData放入终端页面的一个Div元...

    2 个月前
  • 😉我用 Nuxt.js 仿了个掘金

    前言 首先肯定是要夸夸掘金啦,最开始从 CSDN 到 博客园 再到 掘金,个人感觉掘金的技术氛围非常的nice,真是个宝藏社区👏。技术文章大多以前端为主,对前端开发者非常友好,质量也是歪瑞古的。

    3 个月前
  • 😀一个原生js弹幕库

    danmujs 😀一个原生js弹幕库,基于 CSS3 Animation 地址、核心代码 本项目基于 rcbullets,项目约70%的代码基于rcbullets,首先要感谢这个项目的作者,如...

    6 个月前
  • 🕵️‍♀️由原型到JS中的“模拟类”

    讲述了有关 JavaScript 中原型相关知识,又引出了 JavaScript 中的“类“究竟是什么?,以及一系列相关问题。 一、前置知识 1、JavaScript 的面向对象(OOP) ​ 面向...

    4 个月前
  • 🔥《吊打面试官》系列 Node.js 必知必会必问!

    (/public/upload/f204a3b224d986128f1b4d9b8d06cd17) 前言 codeing 应当是一生的事业,而不仅仅是 30 岁的青春🍚 本文已收录 Git...

    5 个月前
  • 💖CSS + JS 送学妹满屏幕小爱心

    故事开始 午饭时间,暗恋已久的学妹拉着我的衣袖:“学长学长,你能不能让这些爱心变成五颜六色的吗~”。 我在旁边笑开了花~~~ image.png(/public/upload/04aaa24e...

    4 个月前
  • (干货👍)从详细操作js数组到浅析v8中array.js

    前言 最近在写面试编程题,经常用到数组,经常想偷个懒,用它提供的方法,奈何还是对数组方法使用不熟练,导致写了很多的垃圾代码,很多地方稍加修改的话肯定变得简洁高效优雅👊 所以✍这篇文章本着了解一下Ja...

    1 个月前
  • (vuejs学习)2、使用ElementUI(*)

    1.element安装 开发环境是win10,一到node官网下载node的.msi包(https://npm.taobao.org/mirrors/node/v10.16.0/nodev10.16....

    1 年前

官方社区

扫码加入 JavaScript 社区