有一次我加班到凌晨,咖啡一杯接一杯。
第一杯,精神回來了;
第二杯,手速起飛;
第三杯,感覺自己能寫完一箇中台;
第四杯……心跳開始報警。
我突然意識到:有些東西不是線性增長的,而是指數級爆炸的。
技術世界裏也是這樣。你以為只是“再乘一次”,但結果已經完全不是一個量級了。而 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歲程序員。如果你喜歡我的文章,歡迎關注我的微信公眾號“軟件求生”,獲取更多技術乾貨!