写点什么

理解 JavaScript 模运算符

作者:南城FE
  • 2023-11-06
    广东
  • 本文字数:1853 字

    阅读完需:约 6 分钟

本文翻译自 Understanding the JavaScript Modulo Operator,作者:joshwcomeau, 略有删改。


当我第一次学习编码时,我记得发现模运算符(%)非常令人困惑。😬


当你不明白它的原理的时候,它产生的值看起来完全是随机的:


const what = 10 % 4; // 2const the = 10 % 10; // 0const heck = 4 % 10; // 4
复制代码


在这篇文章中,我们将通过改进除法的心理模型来学习这个运算符是如何工作的,文末还将介绍一个实用的日常实践。


受众群体:这篇博客文章是为初级到中级 JavaScript 开发人员所写。一些 JavaScript 知识是假设的,但核心内容应该对每个人都有用!

重新思考

假设我们有下面的计算:


12 ÷ 4
复制代码


除法常常让人感觉非常抽象或理论化,但有一种实用的方法来思考它:我们可以把一个数字分成大小相等的组。



12 ÷ 4的计算结果为3,因为每个组正好包含 3 个项目。从本质上讲我们正在计算每个组中将包含多少个项目。


在上面的示例中我们的被除数是 12。使用除法时,它可以用很多不同的方式来分割。


假设我们有以下等式:


11 ÷ 4
复制代码


这个方程式的值为 2.75。每组有 2 个完整的项目,然后是另一个项目的 3/4。


如果我们分披萨或蛋糕,这是可行的。但如果这些物品是不可摧毁的呢?如果我们不能把每一项分解成更小的部分呢?


在这种情况下,我们可以将 2 个项目放入每个组,然后剩下 3 个额外的项目放入一个组:



这被称为余数。这是模运算符产生的结果。


在这些数字可以被平均分为几组的情况下(例如,12 ÷ 4),没有余数:


12 % 4; // 0
复制代码


在被除数(要被除的数)不能平均分成几组的情况下,模运算符让我们知道还剩多少:


11 % 4; // 3
复制代码

一个真实的使用案例

我不是一个数学家,我是一个 Web 开发人员。所有这些数学内容都很有趣,接下来让我们谈谈模运算符如何在前端页面上派上用场。


具体来说,有一种问题我似乎经常遇到,模运算符提供了完美的解决方案:循环数组。


假设我们有一个三种颜色的数组。每一秒都想切换到列表中的下一个颜色。当我们到达列表的末尾时,我们就继续回到第一项:



这是一个比较棘手的问题。假设我们有一个名为timeElapsed的变量,它从 0 开始,每秒递增 1。我们必须以某种方式将这个不断增加的值最终映射到一个只有 3 项的数组。


基于以上我们可以编写一个函数,它会产生以下结果:


const COLORS = ['red', 'yellow', 'blue'];getColor({ timeElapsed: 0 }); // 'red'getColor({ timeElapsed: 1 }); // 'yellow'getColor({ timeElapsed: 2 }); // 'blue'getColor({ timeElapsed: 3 }); // 'red'getColor({ timeElapsed: 4 }); // 'yellow'getColor({ timeElapsed: 5 }); // 'blue'getColor({ timeElapsed: 6 }); // 'red'getColor({ timeElapsed: 7 }); // 'yellow'getColor({ timeElapsed: 8 }); // 'blue'
复制代码


让我们看看模运算符如何帮助我们解决这个问题:


const COLORS = ['red', 'yellow', 'blue'];function getColor({ timeElapsed }) {  const colorIndex = timeElapsed % COLORS.length;  return COLORS[colorIndex];}
复制代码


奇迹般地这正是我们所需要的结果!只要timeElapsed是一个整数,这个方法总是返回三种颜色中的一种。它会随着timeElapsed的增加而循环通过 3 种颜色。


COLORS.length等于 3,因为我们的数组中有 3 种颜色。因此随着timeElapsed从 0 递增到 8,该函数最终执行以下计算序列:


const colorIndex = 0 % 3; // 0const colorIndex = 1 % 3; // 1const colorIndex = 2 % 3; // 2const colorIndex = 3 % 3; // 0const colorIndex = 4 % 3; // 1const colorIndex = 5 % 3; // 2const colorIndex = 6 % 3; // 0const colorIndex = 7 % 3; // 1const colorIndex = 8 % 3; // 2
复制代码


然后我们可以使用这个colorIndexCOLORS数组中查找颜色。它保证总是在该数组的可用索引范围内循环。


要理解为什么这样做,值得记住我们的新除法模型:我们试图将timeElapsed分成 3 个大小相等的组,没有任何分数或小数值。余数总是 0、1 或 2。它永远不会是 3+,因为如果还有 3 个,我们可以在每组中再放 1 个!


从本质上讲,这就好像我们有能力创建一个“圆形”数组。无论底层的timeElapsed值增长到多大,我们都可以让它在COLORS数组中无限循环。



在我看来,仅凭这个小技巧,模运算符就值得学习!这些年来,我已经多次使用这种循环数组技巧,这只是模运算符的几个实际用例之一。

最后

本文通过改进除法的心理模型来学习模运算是如何工作的,并介绍了一个很实用的日常实践,希望对你有所帮助。




看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~


专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

发布于: 刚刚阅读数: 4
用户头像

南城FE

关注

还未添加个人签名 2019-02-12 加入

专注前端开发,分享前端知识

评论

发布
暂无评论
理解JavaScript模运算符_JavaScript_南城FE_InfoQ写作社区