Skip to content

面向 JavaScript 开发者的 Rust:值得迈出的一步

如果你来自 JS/TS 世界,对 Rust 感到畏惧,这篇指南就是为你准备的。我们用直接示例将熟悉的概念映射到 Rust 生态系统。

1 分钟 · 657 次阅读
SSSLab

Rust 多年前就出现在 Web 开发者的雷达上,但采用速度很慢。2026 年格局变了:Rust 驱动着 JS 生态系统的关键工具(Biome、Oxc、Rolldown、SWC 编译器),WebAssembly 使其在前端变得不可或缺。是时候学习它了。

目录

最大的思维转变:所有权

在 JavaScript 中,垃圾回收器管理内存。在 Rust 中,责任通过所有权系统转移到编译器。

// 在 JS 中: 这样是可以的
// let a = [1, 2, 3];
// let b = a; // a 仍然有效

// 在 Rust 中:
fn main() {
    let a = vec![1, 2, 3];
    let b = a;          // a "移动"到 b
    println!("{:?}", a); // ✗ 错误: a 已被移动
    println!("{:?}", b); // ✓
}ownership.rs

解决方案:使用引用的借用(borrowing)。

fn main() {
    let a = vec![1, 2, 3];
    let b = &a;          // 不可变借用
    println!("{:?}", a); // ✓ a 仍然有效
    println!("{:?}", b); // ✓
}

fn imprimir(v: &Vec<i32>) { // 接收引用,而非所有权
    for n in v {
        print!("{} ", n);
    }
}borrowing.rs

类型:从 any 到世界上最安全的类型系统

JavaScript/TypeScriptRust 等价物
numberi32, u32, f64, …
stringString (堆) / &str (切片)
T | nullOption<T>
T | ErrorResult<T, E>
any[]Vec<T>
{ [key: string]: T }HashMap<String, T>
fn dividir(a: f64, b: f64) -> Option<f64> {
    if b == 0.0 {
        None   // 等价于 null,但没有那十亿美元的错误
    } else {
        Some(a / b)
    }
}

fn main() {
    match dividir(10.0, 0.0) {
        Some(resultado) => println!("结果: {resultado}"),
        None => println!("除以零"),
    }
}types.rs

错误处理:Result 是 Rust 的 Promise

在 JS 中你用 try/catchPromise 链处理错误。在 Rust 中,Result<T, E> 是惯用方式:

use std::fs;
use std::io;

// 之前: 没有 ? 操作符
fn leer_config_verbose() -> Result<String, io::Error> {
    let contenido = match fs::read_to_string("config.toml") { 
        Ok(c) => c,                                            
        Err(e) => return Err(e),                               
    };                                                         
    Ok(contenido.to_uppercase())
}

// 使用 ? 操作符(等价于 JS 的 await,但用于错误)
fn leer_config() -> Result<String, io::Error> {               
    let contenido = fs::read_to_string("config.toml")?;       
    Ok(contenido.to_uppercase())                               
}errors.rs

闭包和高阶函数

语法不同但概念相同:

fn main() {
    let numeros = vec![1, 2, 3, 4, 5];

    // map + filter + collect(就像 JS 的 Array.map + filter)
    let pares_dobles: Vec<i32> = numeros
        .iter()
        .filter(|&&x| x % 2 == 0)  
        .map(|&x| x * 2)            
        .collect();

    println!("{:?}", pares_dobles); // [4, 8]
}closures.rs

Rust → WebAssembly:通往前端的桥梁

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci(n - 1) + fibonacci(n - 2),
    }
}lib.rs
# 编译为 WASM
wasm-pack build --target web
import init, { fibonacci } from "./pkg/mi_proyecto.js";

await init();
console.log(fibonacci(40)); // 比纯 JS 版本快约 10 倍main.js

从哪里开始

  1. The Rust Book — 任何语言中最好的文档。
  2. Rustlings — 终端中的交互式练习。
  3. Rust by Example — 通过实际示例学习。
  4. wasm-pack 构建一些东西,并在你的当前 Web 项目中使用它。

学习曲线是真实存在的,但 Rust 编译器是你能找到的最好的老师:它的错误信息详细、准确,而且几乎总是包含解决方案。

Anterior
TypeScript 5.x:改变代码编写方式的功能
Siguiente
城市摄影:在城市的混乱中寻找构图