尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

更优雅的写法:proposal-operator-overloading 装饰器接口(@Operators.define)快速上手

更优雅的写法:proposal-operator-overloading 装饰器接口(@Operators.define)快速上手 更优雅的写法proposal-operator-overloading 装饰器接口Operators.define快速上手【免费下载链接】proposal-operator-overloading项目地址: https://gitcode.com/gh_mirrors/pr/proposal-operator-overloadingJavaScript 运算符重载一直是备受关注的话题。proposal-operator-overloading 提案不仅给出了完整的语言设计方案还提供了可实际运行的 shim 运行时与 Babel 转换插件。其中 Operators.define 装饰器接口把运算符定义直接贴在类方法上写法优雅、内聚易读特别适合新手快速上手。本文用最少的代码带你从零体验这套更优雅的 JavaScript 运算符重载写法。什么是 JavaScript 运算符重载JavaScript 原生数值类型非常有限Number 是双精度浮点BigInt 是任意精度整数。想表达十进制数、复数、向量、矩阵等类型时只能依赖库和方法链调用a.mul(x.pow(3)).add(b.mul(x.square()));有了运算符重载同样的逻辑可以写成自然的中缀表达式a * x ** 3 b * x * x d代码一目了然。该提案当前状态虽为 Withdrawn但作者给出了完整可用的实现README.md 记录了设计目标与用法src/ 目录下则是两个可直接安装的 npm 包——也就是说今天我们就能借助 Babel 插件真正跑起来。命令式与装饰器两种定义接口对比提案提供两种定义运算符的接口命令式写法先调用Operators({...})工厂函数生成基类再继承它装饰器写法类上声明Operators.overloaded方法上声明Operators.define()装饰器把运算符定义与业务逻辑放在一起代码更内聚、可读性更强这正是标题所说的更优雅的写法。快速上手第一步安装与配置在项目中安装两个包npm install --save-dev littledan/plugin-transform-operator-overloading npm install --save-prod littledan/operator-overloading-shim然后在.babelrc中加入插件{ plugins: [littledan/plugin-transform-operator-overloading] }完整步骤可参考 src/transform/README.md。插件会负责把运算符表达式转换成 shim 的运行时调用源码见 src/transform/plugin.js。用 Operators.define 定义第一个运算符以最经典的向量加法为例import { Operators } from littledan/operator-overloading-shim; Operators.overloaded class Vector { Operators.define() static add(a, b) { return new Vector(a.contents.map((elt, i) elt b.contents[i])); } } 关键点被Operators.define()装饰的方法签名是(a, b)两个操作数都作为参数传入并不依赖this——这与命令式 API 的语义完全一致。装饰器的实现原理很简单Operators.define会校验装饰对象必须是方法见 src/shim/shim.js再把运算符定义收集起来Operators.overloaded则在类定义完成后通过 finisher 自动生成并挂接运算符基类见 src/shim/shim.js。启用运算符withOperatorsFrom 声明定义好类之后还需在作用域内显式启用运算符重载才会生效function addVectors() { withOperatorsFrom(Vector); return new Vector([1, 2, 3]) new Vector([4, 5, 6]); // Vector([5, 7, 9]) }作用域以代码块为单位推荐只在需要的函数内启用而非模块顶层这样能减少对性能与可预测性的影响见 src/transform/README.md。混合类型运算left 与 right 选项想让3 * vector这样的混合运算成立只需在装饰器上声明另一侧操作数的类型Operators.overloaded class Vector { Operators.define(*) static mul(a, b) { return new Vector(a.contents.map((elt, i) elt * b.contents[i])); } Operators.define(*, { left: Number }) static mulByScalar(a, b) { return new Vector(b.contents.map((elt) elt * a)); } }{ left: Number }表示操作符左侧是 Number 时走这个方法对应的还有{ right: Number }表示右侧为 Number。相同的模式也出现在命令式测试用例中可对照阅读 src/shim/shim.spec.js。一张表看清可重载的运算符类别可重载运算符说明数学运算 - * / % **、一元 - --最常用位运算 ^ \| 、一元~完整支持比较运算 、、由推导索引访问[]、[]会引入 Proxy性能敏感场景慎用不可重载、!、、\|\|、.、()保持语言行为可预测小结装饰器接口带来的三点收益✅内聚运算符定义与类写在同处少了一层工厂函数 继承的样板代码✅直观Operators.define()一眼即知重载了哪个运算符✅安全配合withOperatorsFrom作用域声明重载只在明确启用处生效想阅读完整实现可以克隆仓库git clone https://gitcode.com/gh_mirrors/pr/proposal-operator-overloading重点看 src/shim/shim.js 中的Operators工厂函数src/shim/shim.js与装饰器实现再结合 README.md 中的设计文档你就能完整理解这套优雅的运算符重载方案了。【免费下载链接】proposal-operator-overloading项目地址: https://gitcode.com/gh_mirrors/pr/proposal-operator-overloading创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表