高性能 JavaScript 之位運(yùn)算

引言

如果你是一個(gè)硬件工程師洋侨,那么你對位運(yùn)算相關(guān)的東西必然已經(jīng)非常熟悉,但作為一個(gè)前端工程師的你呢倦蚪?這一點(diǎn)上希坚,確實(shí)比較讓人疑惑。當(dāng)我在學(xué)校里陵且,還在搞硬件相關(guān)的東西的時(shí)候裁僧,一方面的原因是當(dāng)初的應(yīng)用場景很多時(shí)候都會(huì)接觸到,而另一方面慕购,當(dāng)初使用的編程語言并沒有如同 JavaScript 一般靈活方便聊疲。考慮到 ROM/RAM 等因素沪悲,我如果想要依次點(diǎn)亮一排流水燈的時(shí)候获洲,我可能會(huì)使用位移運(yùn)算符配合一個(gè)數(shù)字來標(biāo)記哪顆燈應(yīng)該被點(diǎn)亮;當(dāng)我需要存儲多個(gè)布爾類型的數(shù)據(jù)的時(shí)候殿如,我可能使用掩碼的形式贡珊,存儲和使用需要的信息。但是當(dāng)我習(xí)慣了 JavaScript 提供給我的便利以及運(yùn)行環(huán)境提供給我更大的容量涉馁、更快的計(jì)算速度的時(shí)候门岔,不知不覺間,我竟?jié)u漸忘了之前的編程方式烤送。所以寒随,不如提醒一下自己。

二進(jìn)制與位運(yùn)算

雖然現(xiàn)代瀏覽器帮坚、Nodejs 等為開發(fā)者提供了強(qiáng)大的 JavaScript 運(yùn)行環(huán)境妻往,但是這些環(huán)境的核心仍舊是運(yùn)行在二進(jìn)制的基礎(chǔ)之上的,毋庸置疑的是试和,基于二進(jìn)制數(shù)據(jù)在運(yùn)行位運(yùn)算的時(shí)候遠(yuǎn)比其它數(shù)學(xué)運(yùn)算讯泣、布爾操作等快得多。JavaScript 為開發(fā)者提供了多種位運(yùn)算支持:

  • 按位與(AND灰署,&)
    當(dāng)兩個(gè)操作數(shù)對應(yīng)位數(shù)都是 1 時(shí)判帮,則在該位返回 1局嘁,否則則在該位返回 0溉箕;
1 & 4     // 0,     1 & 100 -> 000
3 & 5     // 1,     11 & 101 -> 001
  • 按位或(OR晦墙,|)
    當(dāng)兩個(gè)操作數(shù)對應(yīng)位數(shù)中至少有一個(gè)是 1 是,則在該位返回 1肴茄,否則則在該位返回 0晌畅;
1 | 4     // 5,     1 | 100 -> 101
3 | 5     // 7,     11 | 101 -> 111
  • 按位異或(XOR,^)
    當(dāng)兩個(gè)操作數(shù)對應(yīng)位數(shù)中兩個(gè)數(shù)中寡痰,一個(gè)為 1抗楔,一個(gè)為 00,則在該位返回 1拦坠,否則則在該位返回连躏;
1 ^ 4     // 5,   1 ^ 100 -> 101
3 ^ 5     // 6,   11 ^ 101 -> 110
  • 按位取反(NOT,~)
    在操作數(shù)對應(yīng)位置贞滨,是 1 則在該位返回 0入热,否則則在該位返回 1;
~1        // -2,  因?yàn)檠a(bǔ)碼存在的原因晓铆,這里可能和期望的有所不同勺良,有興趣可以深入學(xué)習(xí)一下
  • 移位運(yùn)算 (>>, <<, >>>, <<<)
5 >> 1    // 2,    101 >> 1 -> 010
3 << 1    // 6,    11  << 1 -> 110

......

利用位運(yùn)算進(jìn)行性能優(yōu)化

(一) 代替數(shù)學(xué)運(yùn)算

很多情況下,我們可以使用位運(yùn)算替代數(shù)學(xué)運(yùn)算操作骄噪,比如判斷一個(gè)數(shù)是否是奇數(shù)尚困,最典型的做法當(dāng)然是對 2 求余數(shù),也即 if (value % 2) {}链蕊。但與此同時(shí)事甜,二進(jìn)制奇數(shù)的最低位一定是 1,這樣我們就能通過如按位與的方式完成我們的需求滔韵,if (value & 1) {}讳侨。雖然改動(dòng)比較小,但這個(gè)計(jì)算速度卻將因此得到很大的提高奏属。

(二) 位掩碼

位掩碼在一些偏底層的語言中使用得非常廣泛跨跨,但 JavaScript 中卻似乎被大眾給忽略了,更多的情況下囱皿,大家都在關(guān)注業(yè)務(wù)勇婴、功能和兼容性等方面的問題,運(yùn)行環(huán)境中提供的便利的 api 似乎也讓我們覺得沒太大必要使用掩碼技術(shù)嘱腥,但性能要求較高的場景中耕渴,我們還是會(huì)嘗試從一些經(jīng)典的編程范式中尋找答案。用一個(gè)很簡單的例子來說明位掩碼技術(shù):

// 定義所有的可選項(xiàng)
var OPTION_A = 1,
    OPTION_B = 2,
    OPTION_C = 4,
    OPTION_D = 8,
    OPTION_E = 16;

// 包含選項(xiàng) A齿兔、B橱脸、D
var options = OPTION_A | OPTION_B | OPTION_D;      // 1 | 10 | 1000 -> 1011

// 判斷選項(xiàng)是否被包含在 options 中
options & OPTION_A        // 1011 & 1 -> 0001, true
options & OPTION_B        // 1011 & 10 ->  0010, true
options & OPTION_C        // 1011 & 110 -> 0, false
options & OPTION_D        // 1011 & 1000 -> 1000, true
options & OPTION_E        // 1011 & 10000 -> 0, false

之前础米,你可能會(huì)使用比如數(shù)組的 indexOf 或者 Map 數(shù)據(jù)結(jié)構(gòu)等方式來確認(rèn)一個(gè)數(shù)據(jù)在不在你的數(shù)據(jù)集合中,但相比而言添诉,掩碼的運(yùn)算速度遠(yuǎn)比它們高屁桑,除卻函數(shù)調(diào)用帶來額外開銷,位運(yùn)算發(fā)生于系統(tǒng)底層栏赴,尤其是如果有多個(gè)選項(xiàng)保存在一起并需要頻繁檢查的時(shí)候蘑斧,位掩碼將大放異彩。
位運(yùn)算的作用遠(yuǎn)不止如此须眷,我們整個(gè)計(jì)算機(jī)系統(tǒng)都是在其基礎(chǔ)之上構(gòu)建出來的竖瘾,這里羅列的只是冰山一角,歡迎大家?guī)臀已a(bǔ)充~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末花颗,一起剝皮案震驚了整個(gè)濱河市捕传,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扩劝,老刑警劉巖庸论,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異今野,居然都是意外死亡葡公,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門条霜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來催什,“玉大人,你說我怎么就攤上這事宰睡∑研祝” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵拆内,是天一觀的道長旋圆。 經(jīng)常有香客問我,道長麸恍,這世上最難降的妖魔是什么灵巧? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮抹沪,結(jié)果婚禮上刻肄,老公的妹妹穿的比我還像新娘。我一直安慰自己融欧,他們只是感情好敏弃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著噪馏,像睡著了一般麦到。 火紅的嫁衣襯著肌膚如雪绿饵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天瓶颠,我揣著相機(jī)與錄音拟赊,去河邊找鬼。 笑死步清,一個(gè)胖子當(dāng)著我的面吹牛要门,可吹牛的內(nèi)容都是我干的虏肾。 我是一名探鬼主播廓啊,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼封豪!你這毒婦竟也來了谴轮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤吹埠,失蹤者是張志新(化名)和其女友劉穎第步,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缘琅,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粘都,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刷袍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翩隧。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖呻纹,靈堂內(nèi)的尸體忽然破棺而出堆生,到底是詐尸還是另有隱情,我是刑警寧澤雷酪,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布淑仆,位于F島的核電站,受9級特大地震影響哥力,放射性物質(zhì)發(fā)生泄漏蔗怠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一吩跋、第九天 我趴在偏房一處隱蔽的房頂上張望寞射。 院中可真熱鬧,春花似錦钞澳、人聲如沸怠惶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽策治。三九已至脓魏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間通惫,已是汗流浹背茂翔。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留履腋,地道東北人珊燎。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像遵湖,于是被迫代替她去往敵國和親悔政。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,145評論 0 13
  • 運(yùn)算符是處理數(shù)據(jù)的基本方法,用來從現(xiàn)有的值得到新的值萨醒。JavaScript 提供了多種運(yùn)算符,本章逐一介紹這些運(yùn)算...
    許先生__閱讀 604評論 0 3
  • 表達(dá)式 表達(dá)式是由數(shù)字芦瘾、運(yùn)算符、數(shù)字分組符號(如括號)集畅、自由變量和約束變量等以能求得數(shù)值的有意義排列方法所得的組合...
    劼哥stone閱讀 560評論 0 4
  • 打卡
    安心的心靈花園閱讀 238評論 0 0
  • 昨天近弟,在朋友家見到了一盆富貴竹,一下子喜歡上了它挺智。那么大的一盆祷愉,綠意盎然,隨意地插在花瓶里逃贝,確是如此美麗谣辞,一片片狹...
    清淺光陰閱讀 261評論 0 0