JavaScript 的 % 是 remainder(余数)运算符,不是总返回非负结果的数学 modulo。结果通常与被除数同号,所以 -1 % 5 得到 -1,不是 4。
基本用法
12 % 5 // 2
10 % 2 // 0
7 % 3 // 1
-7 % 3 // -1
7 % -3 // 1
除数为 0 时,Number 运算返回 NaN:
10 % 0 // NaN
得到非负取模结果
循环索引、星期和角度归一化经常需要 [0, n):
function modulo(value, divisor) {
return ((value % divisor) + divisor) % divisor
}
modulo(-1, 5) // 4
modulo(6, 5) // 1
调用前应确保 divisor 是符合业务要求的非零有限数。如果允许负除数,还要先定义期望区间,不能只复制公式。
判断奇偶
function isEven(value) {
return value % 2 === 0
}
对整数有效。用户输入应先验证:
function isEvenInteger(value) {
return Number.isInteger(value) && value % 2 === 0
}
循环索引
function nextIndex(current, length) {
if (length <= 0) throw new Error("length must be positive")
return (current + 1) % length
}
function previousIndex(current, length) {
if (length <= 0) throw new Error("length must be positive")
return modulo(current - 1, length)
}
向前移动不会产生负数,向后移动必须处理负余数。
角度归一化
function normalizeDegrees(degrees) {
return modulo(degrees, 360)
}
normalizeDegrees(450) // 90
normalizeDegrees(-90) // 270
动画角度连续变化时,还要考虑从 359° 到 0° 的插值方向,归一化只解决范围问题。
分页和分组
items.forEach((item, index) => {
const column = index % 3
renderInColumn(item, column)
})
CSS Grid 能完成纯布局时优先用 CSS;只有分组逻辑参与数据处理时才需要 %。
BigInt
BigInt 也支持余数,但两侧必须都是 BigInt:
10n % 3n // 1n
// 10n % 3 会抛出 TypeError
BigInt 除数为 0n 会抛出错误,而不是返回 NaN。
浮点数注意事项
0.3 % 0.1 // 可能得到非常接近 0.1 的小数,而不是精确 0
这是二进制浮点表示导致的精度问题。金额和精确步长不要直接依赖浮点 % 判断整除,可以先转换为最小整数单位或使用适合的十进制方案。
更多数组遍历方式可阅读 JavaScript 数组常用方法,异步执行顺序见 Event Loop 指南。
参考资料
继续阅读
JavaScript Event Loop:任务、微任务与渲染顺序
通过调用栈、任务队列、微任务检查点和浏览器渲染流程,解释 Promise、queueMicrotask、setTimeout 与 async/await 的真实执行顺序和常见性能陷阱。
13 分钟JavaScript 数组与遍历:map、splice、for of
按是否修改原数组梳理 map、filter、reduce、find、slice、splice、sort、toSorted,以及 for、forEach、for of、for in 的选择方法。
11 分钟JavaScript 解构与对象复制:浅拷贝、深拷贝
讲清对象和数组解构、展开语法的浅拷贝边界,并比较 structuredClone、JSON 序列化与自定义深拷贝的适用场景。
订阅 FreeMac
每周精选:免费 Mac 软件评测、可信来源更新、替代方案和少折腾指南。