有一次我加班到凌晨,咖啡一杯接一杯。
第一杯,精神回来了;
第二杯,手速起飞;
第三杯,感觉自己能写完一个中台;
第四杯……心跳开始报警。
我突然意识到:有些东西不是线性增长的,而是指数级爆炸的。
技术世界里也是这样。你以为只是“再乘一次”,但结果已经完全不是一个量级了。而 JavaScript 里的指数操作符,本质上讲的,就是这个故事。
什么是指数?先别急着写代码
如果你刚入行的时候,数学不太好(比如我),那“指数”两个字可能自带压力。但换个说法你就懂了。
假设你有 1 块钱:
- 第一天翻 1 倍:2 块
- 第二天再翻 1 倍:4 块
- 第三天再翻 1 倍:8 块
这不是“加钱”,而是每一步都在“复制自己” 。数学上我们写成:
而在 JavaScript 里,以前我们只能这样写:
直到有一天,ECMAScript 说了一句非常人性化的话:“程序员,别受委屈了,给你一个专门的操作符吧。”
于是,指数操作符 ** 登场了。
指数操作符 **,长什么样?
一句话版本:
表示:a 的 b 次方
举几个最直观的例子:
如果你是第一次看到它,可能会觉得:“这不是 Python 吗?”
没错,JavaScript 终于在这件事上,和 Python 达成了“友好外交”。
小米的比喻:指数操作符像“复制机”
我一直觉得,** 很像一个复制机。
- 2 ** 3: 把 2 复制 3 次,然后一股脑乘起来
- 5 ** 1: 复制一次,本质还是自己
- 5 ** 0: 一次都不复制?那就给你一个“默认存在值1”
这也解释了很多新手常问的问题:
“0 不是啥都没有吗?怎么还等于 1?”,从数学和编程实现角度看:0 次方的核心含义不是‘乘’,而是‘不参与’。
** 和 Math.pow,到底该用谁?
这是一个非常经典的“社招面试题衍生问”。我们先直接对比:
从结果看,完全一样。那差别在哪?
1、可读性
比
更接近“人类语言”。
2、运算符优先级
** 是真正的操作符,可以自然参与表达式计算:
如果是 Math.pow,你通常得多写点括号。
3、兼容性(历史问题)
早期浏览器不支持 **,但现在已经不是问题了。现代前端项目,放心用。
4、结论一句话:
**新代码优先 ,老项目维护 Math.pow。
一个很容易踩坑的点:右结合性
重点来了,这是指数操作符最“坑新手”的地方。先看这行代码:
你觉得结果是多少?很多人第一反应是:
但真实结果是:
为什么?因为:指数操作符是“右结合”的。 也就是说:
生活比喻:指数就像“代言人签合同”,先签最里面那一层,再往外扩散。
所以,写指数表达式时,我的建议是:宁可多写括号,也别赌同事的数学水平。
指数操作符 + 负数,会发生什么?
指数和负数一结合,就开始有点“理工味”了。
这表示什么?数学上:
再来一个:
等价于:
指数的负数,本质就是“倒数的指数”。
指数操作符和一元负号,优先级陷阱
来看一个经典“面试杀手”:
你以为是:
但实际结果是:
为什么?因为在 JavaScript 里: **** 的优先级高于一元负号。**
正确写法应该是:
这也是为什么很多规范会建议:只要指数参与负数运算,一定加括号。
在真实业务里,** 用在哪?
你可能会问:“指数听着很学术,真实项目里用得多吗?”
答案是:比你想象得多。
1、动画与缓动函数
很多动画的“先慢后快”“先快后慢”,底层就是指数或幂函数。
2、权重计算
搜索、推荐、排序算法里,经常用指数放大差异:
3、金融、增长模型
复利计算,本质就是指数。
总结
如果让我用一句话总结 JavaScript 的指数操作符: **** 是一个让“增长速度失控”的操作符。**
它看起来只是两个小星号,但背后代表的是:
- 非线性思维
- 数量级跃迁
- 和数学世界的直接连接
如果你还停留在 Math.pow,那只是能用;如果你真正理解 ****** ,那是开始驾驭表达式了。
END
下次你在代码里看到 a ** b,别急着写完就走,想一秒钟: “这是线性增长,还是指数爆炸?”
想清楚这一点,你已经比昨天的自己,又强了一点点。
好朋友们,我们下篇见。
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!