ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

wasm-bindgen 中 `getter` 与 `setter` 属性完全指南:从 JavaScript 属性绑定到 Symbol 访问器

wasm-bindgen 中 `getter` 与 `setter` 属性完全指南:从 JavaScript 属性绑定到 Symbol 访问器 开发工具【免费下载链接】wasm-bindgenFacilitating high-level interactions between Wasm modules and JavaScript项目地址https://gitcode.com/gh_mirrors/wa/wasm-bindgen点击查看免费下载本指南聚焦 wasm-bindgen 的#[wasm_bindgen(method, getter)]与#[wasm_bindgen(method, setter)]属性讲解如何在 Rust 中声明 JavaScript 类实例属性的读取与写入访问器。你将掌握默认命名规则getter 同名、setter 的set_前缀、通过属性参数显式指定属性名、structural与默认原型链缓存两种访问模式的差异以及[Symbol.name]形式的 well-known symbol 绑定技巧。一、属性概述把 JavaScript 属性当作 Rust 方法调用getter和setter是两个只能与method组合使用的属性method的完整说明见 method 属性。它们把 Rust 中导入的函数声明标记为对 JavaScript 对象属性的访问器带getter的函数默认访问与Rust 函数同名的 JavaScript 属性带setter的函数函数名必须以set_开头实际访问的属性名是set_之后的后缀部分。这一规则由宏解析器在语法层面直接落地在 crates/macro-support/src/parser.rs 中getter与setter被解析为Getter(Span, OptionString)与Setter(Span, OptionString)两个可带可选字符串参数的属性随后在 同文件 L3352-L3356 处被转换为ast::OperationKind::Getter/Setter操作类别。二、默认命名规则与最小可用示例假设 JavaScript 端有一个对white_russians属性定义 getter/setter 的类class TheDude { get white_russians() { ... } set white_russians(val) { ... } }对应的 Rust 导入写法如下#[wasm_bindgen] extern C { type TheDude; #[wasm_bindgen(method, getter)] fn white_russians(this: TheDude) - u32; #[wasm_bindgen(method, setter)] fn set_white_russians(this: TheDude, val: u32); }这里导入了TheDude类型并定义了访问每个实例white_russians属性的能力第一个函数是 getter在 Rust 中通过the_dude.white_russians()调用方法式调用第二个函数是 setter通过the_dude.set_white_russians(2)写入值。注意由于两个函数都标记了method因此必须带有this: TheDude作为第一个参数详见 method 属性。三、显式指定属性名getter name/setter namegetter和setter都可以携带一个字符串参数用来显式声明实际访问的属性名。一旦显式指定对 Rust 函数名就不再有任何约束getter 不再要求同名setter 不再要求set_前缀#[wasm_bindgen] extern C { type TheDude; #[wasm_bindgen(method, getter white_russians)] fn my_custom_getter_name(this: TheDude) - u32; #[wasm_bindgen(method, setter white_russians)] fn my_custom_setter_name(this: TheDude, val: u32); }这段代码与上一节完全等价两个函数虽然在 Rust 中叫my_custom_getter_name/my_custom_setter_name但访问的都是white_russians属性。这一显式形式也方便同时使用js_name进一步控制 Rust 侧标识符二者可以自由组合属性名与js_name的交互规则在测试中有系统验证见下文。四、两种访问模式默认原型缓存 vsstructural务必注意getter/setter函数在加载时只从构造函数的原型链上查找一次结果被缓存之后每次访问都直接调用缓存下来的访问器accessor。默认模式下Rust 调用the_dude.white_russians()实际生成的 JavaScript 等价于// 这是默认情况下 Rust 调用 the_dude.white_russians() 时所执行的逻辑 const white_russians Object.getOwnPropertyDescriptor( TheDude.prototype, white_russians ).get;也就是说访问器函数指针在模块初始化时就被钉死。如果需要在每一次访问时都动态遍历原型链例如对象被继承、属性被动态覆写或传入的不是该构造函数的实例请加上structural属性// 这是加上 structural 之后的效果 const white_russians function(the_dude) { return the_dude.white_russians; };structural的具体语义见 structural 属性它表示以结构化、鸭子类型的方式访问方法或属性每次访问都沿原型链实时查找。该文档同时指出自 [RFC 5] 之后structural已是所有导入函数的默认行为属性本身目前很大程度上被忽略、仅为向后兼容保留其反面final属性 反而更具功能意义。因此对getter/setter而言原型链缓存对应的是非structural即final语义加不加structural决定了访问器是静态固化还是动态查找。源码层面的两种生成路径这两种模式在编译器中对应完全不同的代码生成分支可以从 crates/cli-support/src/wit/mod.rs 中清晰地看到structural模式下getter 被转译为AuxImport::StructuralGetter(field)setter 被转译为AuxImport::StructuralSetter(field)静态成员则对应StructuralClassGetter/StructuralClassSetter非structural模式下则生成AuxValue::Getter(class, field)/AuxValue::Setter(class, field)静态成员对应ClassGetter/ClassSetter走的是加载时取访问器的 Value 管线。随后在 crates/cli-support/src/js/mod.rs 中StructuralGetter被内联生成receiver 属性访问的表达式严格断言只允许 1 个参数StructuralSetter则生成receiver 属性访问 新值的赋值表达式严格断言恰好 2 个参数。这些断言与文档中getter 带this、setter 带this和val的签名约定一一对应。五、非合法标识符与原型链兜底编译器如何保证正确性property_accessor是生成属性访问表达式的核心辅助函数定义在 crates/cli-support/src/js/mod.rs属性名是合法 JS 标识符时生成点号访问如foo.bar属性名不是合法 JS 标识符时自动转为方括号字符串形式如foo[kebab-case]以[开头、以]结尾的名称被视为计算键表达式原样拼接这正是[Symbol.iterator]这类 Symbol 键的入口见下文点分路径如prototype.set.call会按.拆分后逐段渲染以保留历史行为。另外由于默认模式在加载时要沿原型链查找访问器而个别浏览器存在将描述符上移到原型链的异常行为编译器内置了一个GetOwnOrInheritedPropertyDescriptor兜底函数手动遍历原型链定位属性描述符见 crates/cli-support/src/js/mod.rs。这是默认缓存模式稳定性的底层保障。六、绑定 well-known symbol 访问器getter和setter都支持显式的方括号字符串形式[Symbol.name]用于绑定以 well-known symbol 为键的访问器#[wasm_bindgen] extern C { #[wasm_bindgen(js_name String)] type JsString; #[wasm_bindgen(method, js_class String, getter [Symbol.toPrimitive])] fn to_primitive(this: JsString) - String; }这段代码绑定的是String.prototype上的[Symbol.toPrimitive]getter注意同时使用了js_class String指定构造函数js_name与js_class的配合规则见 js_name 属性。关于该语法有三点限制只接受精确形式[Symbol.ident][ ... ]内部不支持任意表达式同样的语法也被js_name支持用于非 getter/setter 的普通导入例如js_namespace SomeClass, js_name [Symbol.toPrimitive]的静态调用或method, js_class String, js_name [Symbol.iterator]的方法绑定从前文可知property_accessor正是通过以[开头、以]结尾即按计算键原样拼接这一规则来识别并透传 Symbol 键的。七、测试验证getter/setter 全组合矩阵仓库提供了系统性的测试来验证 getter/setter 与js_name、显式属性名之间的全部组合见 tests/wasm/getters_and_setters.rs 与配套的 tests/wasm/getters_and_setters.js。Rust 侧定义了大量命名刻意区分的组合例如无js_name、无显式属性名默认同名 getter、set_前缀 setter仅显式属性名getter new_.../setter new_...函数名完全自由仅js_name重命名 Rust 侧方法名js_name 显式属性名同时使用getter 与 setter 使用相同属性名、不同 Rust 方法名的场景。JS 侧测试脚本则逐一断言默认模式下 Rust 方法以函数调用形式出现rules.no_js_name__...()而getter/setter声明的属性以直接属性读写的形式出现rules.new_js_name__... value * 2从而端到端验证了编译产物的行为符合文档所述语义。八、快速参考关键规则一览规则说明组合前提必须与method一起使用函数需带this: T参数getter 默认命名访问与 Rust 函数同名的 JS 属性setter 默认命名Rust 函数名必须以set_开头访问set_之后的部分显式指定getter prop/setter prop指定后函数名无任何限制默认访问模式加载时沿构造函数原型链查找一次并缓存访问器structural每次访问动态遍历原型链当前已是默认语义属性主要为向后兼容保留Symbol 键仅接受精确形式[Symbol.ident]同语法亦适用于js_name实例 vs 静态实例访问器作用于实例对象静态成员由编译器生成ClassGetter/ClassSetter分支综上getter/setter属性是 wasm-bindgen 在 Rust 侧表达 JavaScript 属性访问的标准方式默认命名规则让常见场景零配置即可工作显式属性名与js_name的组合提供了完整的命名自由structural切换访问模式而[Symbol.name]形式打通了 well-known symbol 的绑定通道。理解这三层能力命名、访问模式、Symbol 键后你就能在 Rust 中准确、高效地操作任何 JavaScript 类实例的属性。赞分享开发工具【免费下载链接】wasm-bindgenFacilitating high-level interactions between Wasm modules and JavaScript项目地址https://gitcode.com/gh_mirrors/wa/wasm-bindgen点击查看免费下载相关推荐Chat2DB一个工具连 40 种数据库AI 帮你生成 SQLChat2DB一个工具连 40 种数据库AI 帮你生成 SQL Chat2DB 是一款运行在你自己电脑上的免费数据库客户端与 SQL 工作台。它支持连接开发工具JavaScript 对象属性访问器详解Getter 与 Setter 的妙用JavaScript 对象属性访问器详解Getter 与 Setter 的妙用 前言 在 JavaScript 中对象属性分为两种类型数据属性和访问器属性文档/教程前端howdoi VS Code 扩展离线安装指南基于 .vsix 打包文件完成本地部署howdoi VS Code 扩展离线安装指南基于 .vsix 打包文件完成本地部署 导读 本文基于当前仓库 extension/vscode pkg/ 目录开发工具上一篇开源游戏美术资源库体验记一条克隆命令装满整个明日方舟素材包下一篇Burp Suite 汉化教程3 分钟用免费开源方案让安全测试工具界面说中文创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表