You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于wasm-bindgen实现支持JS解构的Rust WASM构造函数

问题

我正在使用rust-wasm与wasm-bindgen为Rust库创建JavaScript包装器。当前定义的Rust构造函数如下:

#[wasm_bindgen(js_class = Dater)]
impl DaterWrapper {
    #[wasm_bindgen(constructor)]
    pub fn new(
        dts: Option<String>,
        code: Option<String>,
        raw: Option<Vec<u8>>,
        qb64b: Option<Vec<u8>>,
        qb64: Option<String>,
        qb2: Option<Vec<u8>>,
    ) -> Result<DaterWrapper> {
        let dater = Dater::new(
            dts.as_deref(),
            code.as_deref(),
            raw.as_deref(),
            qb64b.as_deref(),
            qb64.as_deref(),
            qb2.as_deref(),
        )
        .as_js()?;
        Ok(DaterWrapper(dater))
}

它生成的JavaScript构造函数为:

constructor(dts?: string, code?: string, raw?: Uint8Array, qb64b?: Uint8Array, qb64?: string, qb2?: Uint8Array);

该构造函数不支持JavaScript解构。我希望通过解构实现命名参数构造,例如new Dater({dts: now_datetime}),请问如何修改Rust构造函数以支持该调用方式?

解决方案

要实现JS的命名参数构造,得定义一个结构体来映射JS传入的配置对象,然后在构造函数中接收这个结构体作为参数。具体操作如下:

1. 定义配置结构体

先创建一个与JS配置对象对应的Rust结构体,用#[wasm_bindgen]标记,确保wasm-bindgen能生成对应的JS类型:

#[wasm_bindgen]
pub struct DaterOptions {
    pub dts: Option<String>,
    pub code: Option<String>,
    pub raw: Option<Vec<u8>>,
    pub qb64b: Option<Vec<u8>>,
    pub qb64: Option<String>,
    pub qb2: Option<Vec<u8>>,
}

结构体字段名要和你期望的JS对象属性名完全一致,且都设为Option类型以支持可选参数。

2. 修改构造函数参数

把原构造函数的多个参数替换成这个配置结构体:

#[wasm_bindgen(js_class = Dater)]
impl DaterWrapper {
    #[wasm_bindgen(constructor)]
    pub fn new(options: DaterOptions) -> Result<DaterWrapper> {
        let dater = Dater::new(
            options.dts.as_deref(),
            options.code.as_deref(),
            options.raw.as_deref(),
            options.qb64b.as_deref(),
            options.qb64.as_deref(),
            options.qb2.as_deref(),
        )
        .as_js()?;
        Ok(DaterWrapper(dater))
    }
}

3. (可选)支持无参数调用

如果需要允许new Dater()这种无参数调用,给构造函数的参数加上Option包裹,并为DaterOptions实现Default trait:

// 实现Default trait,生成默认空配置
impl Default for DaterOptions {
    fn default() -> Self {
        DaterOptions {
            dts: None,
            code: None,
            raw: None,
            qb64b: None,
            qb64: None,
            qb2: None,
        }
    }
}

// 修改构造函数
#[wasm_bindgen(js_class = Dater)]
impl DaterWrapper {
    #[wasm_bindgen(constructor)]
    pub fn new(options: Option<DaterOptions>) -> Result<DaterWrapper> {
        let opts = options.unwrap_or_default();
        let dater = Dater::new(
            opts.dts.as_deref(),
            opts.code.as_deref(),
            opts.raw.as_deref(),
            opts.qb64b.as_deref(),
            opts.qb64.as_deref(),
            opts.qb2.as_deref(),
        )
        .as_js()?;
        Ok(DaterWrapper(dater))
    }
}

最终效果

修改后生成的JS构造函数会变为:

constructor(options?: DaterOptions);

现在你可以用命名参数的方式调用:

// 仅传入dts参数
const dater1 = new Dater({ dts: now_datetime });

// 传入多个参数
const dater2 = new Dater({ dts: "2024-05-20", code: "CN", raw: new Uint8Array([1,2,3]) });

// 无参数调用(如果做了可选处理)
const dater3 = new Dater();

内容的提问来源于stack exchange,提问作者daidoji70

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 01:18:14