WebAssembly

JS在引擎中的过程

词法分析:分词生成token

一个个字幕扫描,与定义好的JavaScript关键字进行比较。token是不可分割的最小单元。

js 复制代码
    [
      { type: 'Const', value: 'const', start: 0, end: 5 },
      { type: 'Identifier', value: 'a', start: 6, end: 7 },
      { type: 'Assign', value: '=', start: 8, end: 9 },
      { type: 'Number', value: '1', start: 10, end: 11, raw: '1' },
      { type: 'Semicolon', value: ';', start: 11, end: 12 },
    ]

语法分析:通过Parser生成AST(规定结构的对象)

生成中间字节码

由解释器生成可运行的字节码。(为了在跨平台的基础上做到提升效率,保护代码安全)

热点代码编译成机器码

被即时编译器转换成机器码。只有热点代码会编译成机器码,为了平衡启动速度和执行效率。热点代码(例如多次调用的函数,多次循环体等),引擎通过性能计数器监控代码执行频率,当达到阈值时触发编译。

可以看到,代码中的热点代码会被进行编译成机器码,下一次执行就能直接执行机器码来提高效率。但是我们JS中是动态类型的语言,一个变量可以赋值给不同的类型。就行这次翻译的机器码限定类型为Object类型,下次执行到发现是Array类型,那么又要重新进行编译。

asm.js出现

asm.js是一个Javascript的严格子集,合理合法的asm.js代码一定是合理合法的JavaScript代码,但是反之就不成立。同WebAssembly一样,asm.js不是用来给各位用手一行一行撸 的代码,asm.js是一个编译目标

C / C++ 编译成 JS 有两个最大的困难。

  • C / C++ 是静态类型语言,而 JS 是动态类型语言。
  • C / C++ 是手动内存管理,而 JS 依靠垃圾回收机制。

asm.js 就是为了解决这两个问题而设计的:它的变量一律都是静态类型,并且取消垃圾回收机制。 除了这两点,它与 JavaScript 并无差异,也就是说,asm.js 是 JavaScript 的一个严格的子集,只能使用后者的一部分语法。

asm.js强制静态类型,举个例子。

js 复制代码
function asmJs() { 
'use asm'; 
let myInt = 0 | 0; 
let myDouble = +1.1; 
}

WebAssembly

如果你对 JS 比较了解,可能知道还有一种叫做 WebAssembly 的技术,也能将 C / C++ 转成 JS 引擎可以运行的代码。那么它与 asm.js 有何区别呢?

回答是,两者的功能基本一致,就是转出来的代码不一样:asm.js 是文本,WebAssembly 是二进制字节码,因此运行速度更快、体积更小。从长远来看,WebAssembly 的前景更光明。

优点:

  1. 🚀 性能接近原生 (Near-Native Performance)

这是 Wasm 最广为人知的优点。通过预编译的二进制格式和高效的 JIT 编译到原生机器码,Wasm 在执行 CPU 密集型任务时远超传统 JavaScript。

  • 应用场景:3D 游戏、视频/音频处理、科学计算、加密、物理模拟。
  1. 🌐 语言生态的极大扩展 (Language Ecosystem Expansion)

Wasm 允许开发者使用他们最擅长的语言来为 Web 编写高性能模块,而不仅仅局限于 JavaScript。

  • 支持的语言:C, C++, Rust 是"一等公民",Go, C#, Swift, Python, Java 等也通过不同工具链得到了支持。
  • 核心价值:这意味着可以将数十年积累下来的、经过实战检验的非 JS 库和应用移植到 Web 上。

缺点:

  1. 🌉 与 JavaScript 的交互开销 (JavaScript Interop Overhead)

这是目前 Wasm 最大的性能陷阱。频繁地在 JS 和 Wasm 之间来回调用函数或传递数据是非常昂贵的。

  • 问题根源:数据需要在线性内存和 JS 对象之间来回复制和转换。

  • 负面影响:如果使用不当(例如,用 Wasm 频繁操作 DOM),性能可能比纯 JS 实现还要差得多。

  1. 🕸️ 无法直接访问 Web API (No Direct Web API Access)

Wasm 被关在沙箱里,它不能像 JS 那样直接调用 document.getElementById()fetch()。所有这些操作都必须通过 JS 作为"中间人"来完成,这增加了复杂性和"胶水代码"的数量。

相关推荐
Lsx_13 分钟前
分不清RAG 、Function Call、MCP、Agent?一文秒懂它们的区别和联系
前端·agent·mcp
毕了业就退休34 分钟前
websocket 的心跳机制你知道几种
前端·javascript·http
子林super35 分钟前
aiforcast集群单节点CPU使用率100%问题
前端
CF14年老兵36 分钟前
为什么 position: absolute 在 Flexbox 里会失效?
前端·css·trae
xianxin_41 分钟前
CSS 选择器
前端
徐小夕42 分钟前
花3个月时间,写了一款协同文档编辑器
前端·vue.js·算法
Nicholas681 小时前
flutter滚动视图之ScrollDirection、ViewportOffset源码解析(一)
前端
Dream耀1 小时前
FitKick 电商APP项目总结二
前端·javascript·react.js
ZsTs1191 小时前
一篇通关:从 MVVM 到渲染优化,Vue 基础核心 5 大模块全解析
前端·vue.js·面试
石小石Orz1 小时前
视差悬停特效:鼠标跟随的沉浸式交互体验
前端·css·trae