逻辑运算符
a-calc 3.x 引入了完整的逻辑运算符支持,包括与、或、非运算,并实现了短路求值。
支持的运算符
| 运算符 | 名称 | 含义 | 示例 |
|---|---|---|---|
&& | 逻辑与 | 两个条件都为真时返回真 | true && true → true |
|| | 逻辑或 | 任一条件为真时返回真 | false || true → true |
! | 逻辑非 | 取反 | !false → true |
基本用法
逻辑与 (&&)
javascript
import { calc } from 'a-calc'
// 布尔值运算
calc('true && true') // true
calc('true && false') // false
calc('false && true') // false
calc('false && false') // false
// 与比较运算组合
calc('5 > 3 && 2 > 1') // true
calc('5 > 3 && 2 < 1') // false
// 使用变量
calc('x > 0 && y > 0', { x: 5, y: 3 }) // true逻辑或 (||)
javascript
// 布尔值运算
calc('true || true') // true
calc('true || false') // true
calc('false || true') // true
calc('false || false') // false
// 与比较运算组合
calc('5 < 3 || 2 > 1') // true
calc('5 < 3 || 2 < 1') // false
// 使用变量
calc('x < 0 || y < 0', { x: -5, y: 3 }) // true逻辑非 (!)
javascript
// 基本取反
calc('!true') // false
calc('!false') // true
// 与比较运算组合
calc('!(5 > 3)') // false
calc('!(5 < 3)') // true
// 双重否定
calc('!!true') // true
calc('!!false') // false短路求值
逻辑运算符实现了短路求值(Short-circuit Evaluation),可以避免不必要的计算:
&& 的短路
当 && 左侧为假时,右侧不会被计算:
javascript
// 左侧为假,右侧不执行
calc('false && (1/0 > 0)') // false(不会触发除零错误)
// 实际应用:安全的条件检查
calc('x != 0 && 10/x > 1', { x: 0 }) // false(避免除零)|| 的短路
当 || 左侧为真时,右侧不会被计算:
javascript
// 左侧为真,右侧不执行
calc('true || (1/0 > 0)') // true(不会触发除零错误)
// 实际应用:默认值模式
calc('x > 0 || y > 0', { x: 5, y: 'invalid' }) // true(y 不会被计算)真值判断规则
逻辑运算符会将操作数转换为布尔值,转换规则如下:
| 值类型 | 假值 (false) | 真值 (true) |
|---|---|---|
| 布尔值 | false | true |
| 数字 | 0 | 非零数字 |
| 字符串 | "" 或 "0" | 其他字符串 |
| Decimal | 0 | 非零 |
javascript
// 数字作为布尔值
calc('0 && true') // false(0 为假)
calc('1 && true') // true(1 为真)
calc('0 || true') // true
calc('1 || false') // true
// 字符串作为布尔值
calc('"" || true') // true(空字符串为假)
calc('"0" || true') // true("0" 字符串为假)
calc('"a" && true') // true(非空非"0"字符串为真)组合使用
多条件组合
javascript
// 多个 && 组合
calc('a > 0 && b > 0 && c > 0', { a: 1, b: 2, c: 3 }) // true
calc('a > 0 && b > 0 && c > 0', { a: 1, b: 0, c: 3 }) // false
// 多个 || 组合
calc('a < 0 || b < 0 || c < 0', { a: 1, b: -1, c: 3 }) // true
// && 和 || 混合
calc('(a > 0 && b > 0) || c > 0', { a: -1, b: -1, c: 5 }) // true
calc('a > 0 && (b > 0 || c > 0)', { a: 1, b: -1, c: 5 }) // true与条件表达式组合
javascript
// 逻辑运算作为条件
calc('(x > 0 && y > 0) ? x + y : 0', { x: 3, y: 4 }) // '7'
calc('(x > 0 || y > 0) ? 1 : 0', { x: -1, y: 2 }) // '1'
// 复杂条件
calc('(!invalid && value > 0) ? value : defaultVal', {
invalid: false,
value: 100,
defaultVal: 0
}) // '100'与函数组合
javascript
// 函数结果参与逻辑运算
calc('sqrt(x) > 0 && abs(y) < 10', { x: 16, y: -5 }) // true
// 条件执行函数
calc('x > 0 ? sqrt(x) : abs(x)', { x: -16 }) // '16'运算符优先级
逻辑运算符的优先级如下(从高到低):
| 运算符 | 优先级 | 结合性 |
|---|---|---|
! | 9 | 右结合 |
&& | 3 | 左结合 |
|| | 2 | 左结合 |
javascript
// ! 优先级最高
calc('!true && false') // false(等价于 (!true) && false)
calc('!(true && false)') // true(使用括号改变优先级)
// && 优先级高于 ||
calc('true || false && false') // true(等价于 true || (false && false))
calc('(true || false) && false') // false(使用括号改变优先级)实际应用示例
表单验证
javascript
// 多条件验证
const validateForm = (data) => calc(`
name != "" &&
age >= 18 &&
age <= 100 &&
email != ""
`, data)
validateForm({ name: 'John', age: 25, email: 'john@example.com' }) // true
validateForm({ name: '', age: 25, email: 'john@example.com' }) // false权限检查
javascript
// 检查用户权限
const hasAccess = (user) => calc(`
(role == "admin") ||
(role == "editor" && department == targetDept)
`, { ...user, targetDept: 'IT' })
hasAccess({ role: 'admin', department: 'HR' }) // true
hasAccess({ role: 'editor', department: 'IT' }) // true
hasAccess({ role: 'editor', department: 'HR' }) // false
hasAccess({ role: 'viewer', department: 'IT' }) // false商品可购买判断
javascript
// 判断商品是否可购买
const canBuy = (product, user) => calc(`
stock > 0 &&
!disabled &&
(price <= budget || isVip)
`, { ...product, ...user })
canBuy(
{ stock: 10, disabled: false, price: 100 },
{ budget: 80, isVip: true }
) // true(VIP可以超预算购买)
canBuy(
{ stock: 0, disabled: false, price: 50 },
{ budget: 100, isVip: false }
) // false(无库存)日期范围检查
javascript
// 检查是否在有效期内
const isValid = (item) => calc(`
currentTime >= startTime &&
currentTime <= endTime &&
!expired
`, item)
isValid({
currentTime: 1000,
startTime: 500,
endTime: 1500,
expired: false
}) // true注意事项
- 短路求值:利用短路特性可以避免不必要的计算和潜在错误
- 类型转换:非布尔值会按规则转换,注意
"0"字符串被视为假值 - 优先级:复杂表达式建议使用括号明确优先级
- 与格式化:逻辑运算返回布尔值,格式化参数会被忽略
- || 与 |:注意
||是逻辑或运算符,单个|是格式化分隔符