链式计算
链式计算提供流式 API 风格的计算方式,通过方法链实现连续运算。采用函数返回函数的设计,简洁高效。
设计理念
- c 前缀起始:链式调用以
cadd、cmul等带 c 前缀的函数开始 - 无前缀延续:链上后续方法不带 c 前缀,如
.add()、.mul() - 函数返回函数:返回可调用的函数对象,再加括号即输出结果
- 任意参数:每个方法支持传入任意数量参数
- 支持嵌套:参数可以是链式对象或函数调用结果,实现复杂表达式
基础语法
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"嵌套链式调用(新功能)
链式函数的参数支持:
- 普通数字和字符串
- 其他链式对象(函数)
add、mul等函数的调用结果
这使得可以构建复杂的嵌套表达式:
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"优势与适用场景
链式调用的优势
- 可读性强:代码流程清晰,从上到下阅读
- 易于调试:可以在任何步骤插入调试代码
- 支持嵌套:通过嵌套链式对象处理复杂表达式
- 类型安全:完整的 TypeScript 类型支持
- 错误传播:错误会自动传播,无需手动检查
适用场景
- ✅ 顺序计算:价格计算、折扣、税费等
- ✅ 多步骤处理:需要多个步骤的数据处理
- ✅ 嵌套表达式:需要括号优先级的复杂计算
- ✅ 可读性优先:团队协作,代码需要易于理解
- ❌ 简单表达式:
1 + 2 * 3这种直接用calc()更简洁