Skip to content

链式计算

链式计算提供流式 API 风格的计算方式,通过方法链实现连续运算。采用函数返回函数的设计,简洁高效。

设计理念

  1. c 前缀起始:链式调用以 caddcmul 等带 c 前缀的函数开始
  2. 无前缀延续:链上后续方法不带 c 前缀,如 .add().mul()
  3. 函数返回函数:返回可调用的函数对象,再加括号即输出结果
  4. 任意参数:每个方法支持传入任意数量参数
  5. 支持嵌套:参数可以是链式对象或函数调用结果,实现复杂表达式

基础语法

js
import { cadd, cmul, csub, cdiv } from 'a-calc'

// 基础用法
cadd(1, 2, 3)()                  // "6"
cmul(2, 3, 4)()                  // "24"

// 链式调用
cadd(1, 2).mul(3)()              // "9"
cmul(10, 10).sub(1)()            // "99"
csub(100, 20, 10).div(2)()       // "35"

嵌套链式调用(新功能)

链式函数的参数支持:

  • 普通数字和字符串
  • 其他链式对象(函数)
  • addmul 等函数的调用结果

这使得可以构建复杂的嵌套表达式:

js
// 嵌套链式对象
cadd(1, cadd(2, 3))()            // 1 + (2 + 3) = "6"
cmul(cadd(1, 2), cadd(3, 4))()   // (1 + 2) * (3 + 4) = "21"

// 多层嵌套
cadd(
  cmul(cadd(1, 2), 3),           // (1 + 2) * 3 = 9
  cmul(cadd(4, 5), 2)            // (4 + 5) * 2 = 18
)()                               // 9 + 18 = "27"

// 混合使用函数调用
import { add, mul } from 'a-calc'
cadd(
  add(10, 20, "string"),         // 30
  cadd(5, 5)                     // 10
)()                               // "40"

起始方法

c 为前缀的起始方法:

方法说明初始行为参数支持
cadd(...nums)加法起始所有参数相加数字、字符串、链式对象、函数调用
csub(...nums)减法起始第一个参数减去其余参数数字、字符串、链式对象、函数调用
cmul(...nums)乘法起始所有参数相乘数字、字符串、链式对象、函数调用
cdiv(...nums)除法起始第一个参数除以其余参数数字、字符串、链式对象、函数调用
cmod(...nums)取模起始依次取模数字、字符串、链式对象、函数调用
cpow(...nums)幂运算起始依次求幂数字、字符串、链式对象、函数调用
cidiv(...nums)整除起始依次整除数字、字符串、链式对象、函数调用
js
cadd(1, 2, 3)()     // 1 + 2 + 3 = "6"
csub(100, 20, 10)()  // 100 - 20 - 10 = "70"
cmul(2, 3, 4)()      // 2 * 3 * 4 = "24"
cdiv(100, 2, 5)()    // 100 / 2 / 5 = "10"
cmod(17, 5)()        // 17 % 5 = "2"
cpow(2, 3, 2)()      // (2 ^ 3) ^ 2 = "64"
cidiv(17, 5)()       // 17 // 5 = "3"

// 支持嵌套
cmul(cadd(2, 3), cdiv(10, 2))()  // (2 + 3) * (10 / 2) = "25"

链式方法

链上方法 不带 c 前缀,同样支持链式对象和函数调用作为参数:

方法说明参数支持
.add(...nums)加上所有参数数字、字符串、链式对象、函数调用
.sub(...nums)减去所有参数数字、字符串、链式对象、函数调用
.mul(...nums)乘以所有参数数字、字符串、链式对象、函数调用
.div(...nums)除以所有参数数字、字符串、链式对象、函数调用
.mod(...nums)对所有参数依次取模数字、字符串、链式对象、函数调用
.pow(...nums)对所有参数依次求幂数字、字符串、链式对象、函数调用
.idiv(...nums)对所有参数依次整除数字、字符串、链式对象、函数调用
js
cadd(10)
  .add(5, 3)      // 10 + 5 + 3 = 18
  .mul(2)          // 18 * 2 = 36
  .sub(6)          // 36 - 6 = 30
  ()               // "30"

cmul(100)
  .div(4)          // 100 / 4 = 25
  .add(75)        // 25 + 75 = 100
  .mul(0.8, 0.9)   // 100 * 0.8 * 0.9 = 72
  ()               // "72"

// 链式方法中使用嵌套
cadd(10)
  .add(cadd(2, 3))     // 10 + (2 + 3) = 15
  .mul(csub(10, 5))    // 15 * (10 - 5) = 75
  ()                    // "75"

输出格式控制

最后的调用括号可传入格式化字符串:

js
// 默认返回字符串
cmul(100, 1.1)()           // "110"

// 指定小数位数
cmul(100, 1.1)('=2')       // "110.00"
cdiv(100, 3)('=4')         // "33.3333"

// 千分位
cplus(1000, 234, 567)('=2,')  // "1,801.00"

// 百分比
cmul(0.5, 0.8)('%')        // "40%"
cmul(0.5, 0.8)('%=2')      // "40.00%"

// 所有格式化指令都支持
cplus(1234.5678)('<=2,+')  // "+1,234.57"

参数类型

所有方法支持 数字数字字符串

js
cplus(1, '2', 3)()           // "6"
cmul('100', '1.1')()         // "110"
cplus('1.1', '2.2', '3.3')() // "6.6"

// 混合使用
cplus(100, '50')
  .mul('1.1')
  .sub(10, '5')
  ()  // "150"

使用场景示例

购物车计算

js
const total = cadd(99.9, 199, 49.5)   // 商品价格
  .mul(0.9)                             // 9折
  .sub(20)                              // 满减
  .mul(1.06)                            // 税费
  ('=2')                                // "296.33"

分成计算

js
const share = cmul(10000)              // 总收入
  .sub(1000)                           // 扣除成本
  .mul(0.3)                            // 30% 分成
  ('=2,')                              // "2,700.00"

复利计算

js
const amount = cmul(10000)             // 本金
  .mul(1.05)                           // 第1年
  .mul(1.05)                           // 第2年
  .mul(1.05)                           // 第3年
  ('=2,')                              // "11,576.25"

嵌套复杂计算

js
// 多个商品的总价计算
const item1 = cmul(cadd(99.9, 199), 0.9);     // 商品1打折
const item2 = cmul(cadd(49.5, 50.5), 0.8);    // 商品2打折
const total = cadd(item1, item2);              // 总计
total('=2,')  // "349.01"

// 利润分成计算
const revenue = cadd(10000, 5000);             // 总收入
const cost = cadd(1000, 500);                  // 总成本
const profit = csub(revenue, cost);            // 净利润
const share = cmul(profit, 0.3);               // 30%分成
share('=2')   // "4050.00"

与普通函数对比

js
// 普通方式
const result = calc(`
  ((((100 + 50) * 1.1) - 10) * 0.9) | =2
`)

// 链式方式(更清晰)
const result = cadd(100, 50)
  .mul(1.1)
  .sub(10)
  .mul(0.9)
  ('=2')

// 嵌套链式方式(处理复杂表达式)
const result = cmul(
  csub(
    cmul(cadd(100, 50), 1.1),
    10
  ),
  0.9
)('=2')

// 三种方式结果相同:"139.50"

优势与适用场景

链式调用的优势

  1. 可读性强:代码流程清晰,从上到下阅读
  2. 易于调试:可以在任何步骤插入调试代码
  3. 支持嵌套:通过嵌套链式对象处理复杂表达式
  4. 类型安全:完整的 TypeScript 类型支持
  5. 错误传播:错误会自动传播,无需手动检查

适用场景

  • 顺序计算:价格计算、折扣、税费等
  • 多步骤处理:需要多个步骤的数据处理
  • 嵌套表达式:需要括号优先级的复杂计算
  • 可读性优先:团队协作,代码需要易于理解
  • 简单表达式1 + 2 * 3 这种直接用 calc() 更简洁

基于 MIT 许可发布