Skip to content

函数支持

a-calc 3.x 引入了完整的函数调用支持,你可以在表达式中使用内置函数、自定义函数,并支持函数嵌套调用。

基本语法

函数调用使用标准的括号语法:

functionName(arg1, arg2, ...)

内置函数

a-calc 提供了丰富的内置数学函数,详见内置数学函数章节。

javascript
import { calc } from 'a-calc'

// 数学函数
calc('sqrt(16)')     // '4'
calc('abs(-5)')      // '5'
calc('pow(2, 3)')    // '8'
calc('max(1, 5, 3)') // '5'

// 三角函数
calc('sin(90)')      // '1'
calc('cos(0)')       // '1'

自定义函数

通过 data 参数传入

通过 calc 的第二个参数传入函数:

javascript
import { calc } from 'a-calc'

// 定义自定义函数
const double = (x) => x * 2
const greet = (name) => `Hello, ${name}!`

// 在表达式中使用
calc('double(5)', { double })  // '10'
calc('double(x)', { double, x: 7 })  // '14'

// 支持多参数
const add = (a, b) => a + b
calc('add(3, 4)', { add })  // '7'

// 函数可以返回字符串
calc('greet("World")', { greet })  // 'Hello, World!'

函数参数

数值参数

javascript
calc('sqrt(16)')              // 直接数值
calc('sqrt(x)', { x: 25 })    // 变量
calc('sqrt(4 + 12)')          // 表达式
calc('pow(2, 3 + 1)')         // 多个表达式参数

表达式参数

函数参数可以是任意有效的 a-calc 表达式:

javascript
// 算术表达式作为参数
calc('sqrt(9 + 16)')  // '5' (sqrt(25))
calc('max(1 + 2, 5 - 1)')  // '4'

// 变量表达式
calc('abs(x - y)', { x: 3, y: 10 })  // '7'

// 条件表达式作为参数
calc('abs(x > 0 ? x : -x)', { x: -5 })  // '5'

字符串参数

javascript
// 使用引号包裹字符串
calc('if(status == "active", 100, 0)', { status: 'active' })  // '100'

// 自定义函数处理字符串
const format = (prefix, num) => `${prefix}-${num}`
calc('format("ID", 123)', { format })  // 'ID-123'

函数嵌套

函数可以嵌套调用,内层函数先计算:

javascript
// 嵌套调用
calc('sqrt(pow(3, 2) + pow(4, 2))')  // '5' (勾股定理)

// 多层嵌套
calc('abs(min(-5, max(1, 2)))')  // '5'

// 与变量结合
calc('round(sqrt(x))', { x: 10 })  // '3'

函数与其他特性组合

与条件表达式组合

javascript
// 函数结果作为条件
calc('sqrt(x) > 5 ? "large" : "small"', { x: 36 })  // 'large'

// 条件分支中调用函数
calc('x > 0 ? sqrt(x) : 0', { x: 16 })  // '4'
calc('x > 0 ? sqrt(x) : abs(x)', { x: -9 })  // '9'

与比较运算组合

javascript
calc('sqrt(x) > sqrt(y)', { x: 25, y: 16 })  // true
calc('abs(a) == abs(b)', { a: -5, b: 5 })    // true

与逻辑运算组合

javascript
calc('sqrt(x) > 0 && abs(y) < 10', { x: 16, y: -5 })  // true
calc('min(a, b) > 0 || max(a, b) > 10', { a: -5, b: 15 })  // true

函数查找优先级

当存在同名函数时,a-calc 按以下优先级查找:

  1. data 参数中的函数(最高优先级)
  2. 内置函数(最低优先级)
javascript
import { calc } from 'a-calc'

// 内置的 abs 函数
calc('abs(-5)')  // '5'

// data 参数覆盖内置
const abs = (x) => x * x  // 自定义实现
calc('abs(-5)', { abs })  // '25'

if 条件函数

a-calc 内置了 if 函数,作为三元运算符的替代:

javascript
// if(condition, trueValue, falseValue)
calc('if(x > 0, x, 0)', { x: 5 })   // '5'
calc('if(x > 0, x, 0)', { x: -3 })  // '0'

// 嵌套 if 实现多条件
calc('if(score >= 90, "A", if(score >= 60, "B", "C"))', { score: 75 })  // 'B'

// 与三元运算符等价
calc('x > 0 ? x : 0', { x: 5 })  // 与 if 函数结果相同

高级用法

动态函数名

通过变量引用函数:

javascript
const funcs = {
    add: (a, b) => a + b,
    mul: (a, b) => a * b
}

// 根据条件选择函数
const operation = 'add'
calc(`${operation}(3, 4)`, funcs)  // '7'

函数工厂

创建可配置的函数:

javascript
// 创建带固定参数的函数
const createMultiplier = (factor) => (x) => x * factor

const double = createMultiplier(2)
const triple = createMultiplier(3)

calc('double(5) + triple(3)', { double, triple })  // '19'

递归函数

javascript
// 阶乘函数
const factorial = (n) => n <= 1 ? 1 : n * factorial(n - 1)
calc('factorial(5)', { factorial })  // '120'

// 斐波那契
const fib = (n) => n <= 1 ? n : fib(n - 1) + fib(n - 2)
calc('fib(10)', { fib })  // '55'

注意事项

  1. 函数名规则:函数名必须以字母或下划线开头,可包含字母、数字、下划线
  2. 参数分隔:多个参数使用逗号 , 分隔
  3. 返回值类型:函数可以返回数字、字符串或布尔值
  4. 性能考虑:复杂的嵌套函数调用可能影响计算性能
  5. 错误处理:如果函数执行出错,calc 会返回错误值(默认 -

基于 MIT 许可发布