WebAssembly 会扼杀 JavaScript 吗?让我们一探究竟(附现场演示)🚀
至少在过去的八年里,我一直听到前端即将消亡——或者至少是 JavaScript 即将消亡的说法。据说, WebAssembly(以下简称 WASM)是将会彻底取代前端的工具之一。
很久以前就有人告诉我,JavaScript 基本上已经过时了,我们很快就会用 Rust 或 Go 来编写前端应用程序。
与此同时——尽管我有很多缺点——但我确实有一个优势:我能用简单有趣的方式解释一些事情,即使话题枯燥乏味得令人难以忍受(比如80年代波兰的畜牧业——相信我😅)。
在网上,我找到的文章大多是:
- WASM 统治力吓坏了所有人☠️
- 或者一些非常专业的深度解析,不太适合初学者。
所以我想稍微揭开WASM的神秘面纱,并写一篇客观的文章:
- 为什么它不会很快扼杀 JavaScript
- 而当它真的彻底击败JS的时候
TL;DR 🧠
这里有一个包含 WASM 与 JS 基准测试的小型在线演示以及 GitHub 代码库。
如你看到的:
- JavaScript 本身速度已经非常快,完全可以胜任大多数任务。
- 但说到繁重计算,WASM 就具有很大的优势,即使没有像 SIMD 这样的高级优化也是如此。
你的机器也会出现类似的结果吗?
欢迎在评论区分享!😊
⚠️ 我故意没有验证输入内容 - 请小心,很容易导致浏览器标签页冻结。
演示:https://sylwia-lask.github.io/wasm-js-bench/
仓库:https: //github.com/sylwia-lask/wasm-js-bench
我们到底该如何编写 WebAssembly 代码呢?🤔
让我们从基础知识开始。
编译成 WASM 的代码通常是用以下底层语言编写的:
- 锈
- 去
- C/C++
为什么不选择更方便的语言,比如 Python 或纯 JavaScript 呢?
首先,需要澄清一点🙃
WebAssembly不是原生 CPU 机器代码。
它是一种可移植的字节码格式,浏览器随后会将其即时编译成机器代码——这与浏览器对 JavaScript 的处理方式非常相似。
那么,为什么选择这些语言呢?
Python 或 JS 的主要问题不在于“笨重的编译器”,而在于:
- 动态类型
- 运行时间长
- 垃圾收集
- 不可预测的记忆模型
WASM 的设计理念是围绕一个简单、可预测的执行和内存模型展开的,这更适合 Rust 或 C++ 等语言。
(是的,WASM 垃圾回收机制已经存在并且正在不断发展——但它距离生产环境中的主流应用还很远。)
我为什么使用 Rust 🦀
在我的演示中,我使用了Rust,主要是因为它的运行时间几乎为零,并且可以让你非常明确地控制内存。
我发誓——它的基本配置真的不难设置。我甚至在Windows
上都成功了! 我只需要安装整个 Visual Studio 工具链……这正是我们喜欢 Linux 的原因😌
Rust 本身经常被描述为“打了兴奋剂的 TypeScript”。
这显然不是一回事,但是:
- 它对类型要求非常严格。
- 没有
any - 这对于TypeScript开发者来说,一开始可能会比较恼人……
但你很快就会意识到它能防止多少bug❤️
Rust 还引入了所有权和借用等概念,但这里我就不赘述了。
如果你想深入了解,dev.to 上有很多很棒的 Rust 文章。
编译为 WASM
编译过程本身非常简单,可以轻松集成到您的 CI/CD 管道中。
如果你好奇编译后的输出是什么样子,以及它实际上是如何在 JS 中使用它的,请查看仓库 - 我特意提交了编译后的文件,以便你可以检查它们。
好的,但是……什么时候应该用WASM,什么时候用JS更好呢?⚔️
您可以在演示中自行查看所有内容。
基准测试代码已在 GitHub 上公开,您可以验证我并没有对 WASM 或 JS 进行任何作弊行为 😄
再次强调:输入值由您自行负责——浏览器标签页很容易被冻结。
JavaScript 速度真的很快🏎️
WASM 的速度快得惊人——但浏览器引擎的开发者们也丝毫没有懈怠。像V8或SpiderMonkey
这样的引擎中的 JIT 编译效果也极其出色。
所以如果:
- 你正在编写一个普通的前端应用程序
- 一个简单的 CRUD
- 大量的 DOM 交互
纯 JavaScript总体上速度可能更快。
即使是相当繁重但简单的计算。
例如:
n × n 矩阵乘法并返回一个数字(mod 1 000 000 007)
JS 可以完美地处理这类数学运算,而且通常比 WASM “更快”。
为什么会出现这种情况?
因为我们还要考虑到跨越 JS ↔ WASM 边界的开销。
JS 和 WASM 之间的边界代价很高——你越频繁地跨越它,复制的数据越多,所有性能提升就越快消失。
JS开始走下坡路的地方💥
当涉及到非常繁重的计算时,情况就不同了。
取:
n! mod 1 000 000 007
这里 JavaScript 的速度比 WASM 慢得多。
在这个小例子中,绝对时间仍然很短——但想象一下这样的情况:
- 物理模拟
- 数值求解器
- 大型统计模型
核心问题在于数字。
JavaScript 使用IEEE-754 双精度浮点数,对于非常大的值,它必须切换 到BigInt10 ...u64
单单这一点就会造成巨大的性能差距。
有趣的是,结果会因以下因素而异:
- 浏览器
- JS引擎
- 硬件
例如,在我的电脑上,Firefox 中的差距比 Chrome 中的差距小得多。
图像处理方面呢?🖼️
WASM 经常在以下语境中被提及:
- 图像处理
- 视频
- 声音的
是的——它在这方面确实非常出色。
但这里有个有趣的惊喜😄
当我尝试一个非常简单的基准测试——只是对图像应用高斯模糊——JS完全碾压了 WASM。
为什么?
因为我必须将整个文件复制Uint8Array到 WASM 内存中。
WASM 直到我:才开始赢得比赛
- 构建了完整的图像处理流程。
- 连续应用多个筛选条件
- 在WASM内部尽可能多地完成了工作
吸取教训👇
“WASM 非常适合处理图像”这句话没错——但前提是操作足够繁重。(当然,一些优化(例如共享内存)可以减少这种开销,但代价是增加了复杂性。)
即使是处理数百万像素的高斯模糊,JS 也能出人意料地处理得很好。
额外提示:WASM 并非唯一工具🧰
同样值得注意的是:
- Web Workers
- 屏幕外画布
- GPU解决方案(WebGPU)
……有时也可能是完全可行的替代方案。
并非所有繁重的任务都需要 WASM——有时JS + worker就已经“足够好了”。
所以……JavaScript 要消亡了吗?☠️
不😄
如你看到的:
- JavaScript 仍然非常活跃。
- 现代框架足以满足日常前端工作的需求。
但当需要进行大量计算时:
- 不要害怕WASM
- 它实际上是面向普通开发者的工具,而不仅仅是面向资深系统程序员的工具。
WASM 不是 JavaScript 的替代品,而是一个强大的补充,尤其是在计算引擎方面。
轮到你了!👋
基准测试结果如何?
欢迎在评论区分享——我真的很好奇😊


