你可能不知道的JavaScript位運(yùn)算符詳解
概覽
本文詳細(xì)剖析JavaScript的位運(yùn)算符,其涉及的計(jì)算機(jī)原理和操作效果。
然后從實(shí)戰(zhàn)的角度出發(fā),羅列相關(guān)的應(yīng)用場(chǎng)景。
位操作符概覽
| 運(yùn)算符 | 描述 | 示例 |
|---|---|---|
| 按位與(AND) | 兩個(gè)操作數(shù)對(duì)應(yīng)的比特位都是1時(shí),結(jié)果才為1,否則為0 | 1011 & 0111 = 0011 |
| 按位或(OR) | 兩個(gè)操作數(shù)對(duì)應(yīng)的比特位至少有一個(gè)1時(shí),結(jié)果為1,否則為0 | 1011 | 0111 = 1111 |
| 按位異或(XOR) | 兩個(gè)操作數(shù)對(duì)應(yīng)的比特位有且只有一個(gè)1時(shí),結(jié)果為1,否則為0 | 1011 ^ 0111 = 1100 |
| 按位非(NOT) | 逐個(gè)反轉(zhuǎn)操作數(shù)的比特位,即0變成1,1變成0 | ~1011 = 0100 |
| 左移 | 通過(guò)從右推入零向左位移,并使最左邊的位脫落。 | 1011 << 1 = 10110 |
| 有符號(hào)右移 | 通過(guò)從左推入最左位的拷貝來(lái)向右位移,并使最右邊的位脫落。 | 01011 >> 1 = 00101 |
| 無(wú)符號(hào)右移 | 通過(guò)從左推入零來(lái)向右位移,并使最右邊的位脫落。 | 01011 >>> 1 = 00101 |
位操作支持多少位?
js只支持32位二進(jìn)制數(shù)的位操作,也即能處理的最大十進(jìn)制數(shù)字是 4294967295 。
parseInt('11111111111111111111111111111111', 2); // 4294967295驗(yàn)證下超過(guò)32位二進(jìn)制數(shù)的位操作:
// 33位二進(jìn)制數(shù),得到十進(jìn)制數(shù)字 8589934591
parseInt('111111111111111111111111111111111', 2); // 8589934591
// 對(duì)數(shù)字進(jìn)行無(wú)符號(hào)位右移
8589934591 >>> 0; // 4294967295
4294967295 >>> 0; // 4294967295可以看出,數(shù)字 8589934591 和 4294967295 進(jìn)行 無(wú)符號(hào)位右移0位 操作,得到的結(jié)果是一樣的。
產(chǎn)生這樣結(jié)果的原因,是js的位操作實(shí)現(xiàn),只支持32位。
注意:
ECMAScript中的所有數(shù)值都以IEEE75464位格式存儲(chǔ),只是在位操作的時(shí)候 ,需要轉(zhuǎn)換成32位進(jìn)行操作。
負(fù)數(shù)的無(wú)符號(hào)右移
-2 >>> 1為什么輸出2147483647?
-2在運(yùn)算中,是用補(bǔ)碼表示,即1 1111111111111111111111111111110。
其中,第1位是符號(hào)位。 符號(hào)位1代表當(dāng)前數(shù)字是負(fù)數(shù)。
將-2無(wú)符號(hào)右移1位,則最右邊的0脫落,剩下31位1111111111111111111111111111111,接著,在左側(cè)補(bǔ)0,得到01111111111111111111111111111111。
01111111111111111111111111111111代表十進(jìn)制數(shù)2147483647。
狀態(tài)控制
場(chǎng)景:
以下使用React+TypeScript,實(shí)現(xiàn)游戲狀態(tài)機(jī)的狀態(tài)流轉(zhuǎn),根據(jù)狀態(tài)渲染對(duì)應(yīng)的操作按鈕。
// 游戲狀態(tài)定義
export enum GAME_STATE{
INIT = 1 << 0, // 二進(jìn)制表示:00001
JOIN = 1 << 1, // 二進(jìn)制表示:00010
PREPARE = 1 << 2, // 二進(jìn)制表示:00100
PLAY = 1 << 3, // 二進(jìn)制表示:01000
}// 根據(jù)狀態(tài)渲染按鈕
function RenderButton({state, changeState}){
if((state & GAME_STATE.PLAY) === GAME_STATE.PLAY){
return null;
}
if((state & GAME_STATE.INIT) === GAME_STATE.INIT){
return <button
onClick={() => changeState(GAME_STATE.JOIN)}
>加入游戲</button>
}
if((state & GAME_STATE.JOIN) === GAME_STATE.JOIN){
return <button
onClick={() => changeState(GAME_STATE.PREPARE)}
>準(zhǔn)備游戲</button>
}
if((state & GAME_STATE.PREPARE) === GAME_STATE.PREPARE){
return <button
onClick={() => changeState(GAME_STATE.PLAY)}
>開(kāi)始游戲</button>
}
return null;
}
// 渲染游戲頁(yè)面
function Page(){
const state = useRef(GAME_STATE.INIT);
const changeState = useCallback((newState) => {
state.current = newState;
}, [state]);
return (<div>
// ....other code
<RenderButton state={state.current} changeState={changeState} />
</div>);
}權(quán)限控制
設(shè)計(jì)一個(gè)權(quán)限控制,用于不同角色對(duì)網(wǎng)站文章的權(quán)限分配。
export enum ARTICLE_RULE{
VIEW = 1 << 0, // 查看文章
EDIT = 1 << 1, // 編輯文章
PUBLISH = 1 << 2, // 發(fā)布文章
DELETE = 1 << 3, // 刪除文章
}
export enum ROLE{
GUEST = ARTICLE_RULE.VIEW, // 訪客
ADMIN = ARTICLE_RULE.VIEW | ARTICLE_RULE.EDIT | ARTICLE_RULE.PUBLISH | ARTICLE_RULE.DELETE, // 超級(jí)管理員
OPERATOR = ARTICLE_RULE.VIEW | ARTICLE_RULE.EDIT | ARTICLE_RULE.PUBLISH, // 運(yùn)營(yíng)
}if(user.role === 'admin'){
console.log("user擁有admin權(quán)限");
user.rule = ROLE.ADMIN; // 賦予角色權(quán)限
}
if((user.rule & ARTICLE_RULE.DELETE) === ARTICLE_RULE.DELETE){
console.log("user擁有刪除文章權(quán)限");
}判斷奇偶數(shù)
奇數(shù),最末尾1位,一定是1。
所以將數(shù)字與1(二進(jìn)制表示為:00000000000000000000000000000001)作位操作&。
如果等于1,則是奇數(shù)。
function isOdd(number){
return number & 1 === 1;
}交換兩個(gè)變量的值
let a = 1; let b = 2; a = a ^ b; // 這一步,a緩存了 a ^ b 的結(jié)果 b = a ^ b; // 等價(jià)為: b = a ^ b ^ b, 其中 b ^ b = 0; 所以 b = a ^ 0 = a a = a ^ b; // 同上
判斷整數(shù)是否相等
function isEqual(number1, number2){
return (number1 ^ number2) === 0;
}判斷是否為負(fù)數(shù)
如果是負(fù)數(shù),則對(duì)數(shù)字進(jìn)行 無(wú)符號(hào)右移 位操作,會(huì)變成一個(gè)新的數(shù)字。
所以,如果是負(fù)數(shù),則兩個(gè)數(shù)字不相等。
function isMinus(number){
return number !== (number >>> 0);
}正浮點(diǎn)數(shù)取整
function toInt(floatNumber){
return floatNumber >>> 0;
}正負(fù)浮點(diǎn)數(shù)取整
function toInt(floatNumber){
return floatNumber | 0;
}function toInt(floatNumber){
return ~~floatNumber;
}function toInt(floatNumber){
return floatNumber >> 0;
}十進(jìn)制轉(zhuǎn)換成二進(jìn)制
function dec2bin(dec){
return (dec).toString(2);
}二進(jìn)制轉(zhuǎn)換成十進(jìn)制
function bin2dec(bin){
return parseInt(`${bin}`, 2)
}參考
- 聊聊JavaScript中的7種位運(yùn)算符,看看在實(shí)戰(zhàn)中如何妙用?
- 負(fù)數(shù)的二進(jìn)制表示方法(正數(shù):原碼、負(fù)數(shù):補(bǔ)碼)
到此這篇關(guān)于JavaScript位運(yùn)算符的文章就介紹到這了,更多相關(guān)JS位運(yùn)算符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JavaScript中的數(shù)據(jù)類(lèi)型介紹
- javaScript中一些常見(jiàn)的數(shù)據(jù)類(lèi)型檢查校驗(yàn)
- javascript基本數(shù)據(jù)類(lèi)型和對(duì)象類(lèi)型歸檔問(wèn)題解析
- javascript基礎(chǔ)數(shù)據(jù)類(lèi)型轉(zhuǎn)換教程示例
- javascript數(shù)據(jù)類(lèi)型基礎(chǔ)示例教程
- JavaScript數(shù)據(jù)類(lèi)型轉(zhuǎn)換
- javascript中instanceof運(yùn)算符的用法詳解
- JavaScript中7種位運(yùn)算符在實(shí)戰(zhàn)的妙用
- JavaScript詳細(xì)分析數(shù)據(jù)類(lèi)型和運(yùn)算符
相關(guān)文章
JavaScript下的時(shí)間格式處理函數(shù)Date.prototype.format
這篇文章主要介紹了JavaScript下的時(shí)間格式處理函數(shù)Date.prototype.format的相關(guān)資料,需要的朋友可以參考下2016-01-01
js在數(shù)組中刪除重復(fù)的元素自保留一個(gè)(兩種實(shí)現(xiàn)思路)
遍歷要?jiǎng)h除的數(shù)組arr, 把元素分別放入另一個(gè)數(shù)組tmp中,在判斷該元素在arr中不存在才允許放入tmp中,具體實(shí)現(xiàn)如下,需要的朋友可以看看2014-08-08
微信小程序?qū)崿F(xiàn)watch監(jiān)聽(tīng)
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)watch監(jiān)聽(tīng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
Javascript前端下載后臺(tái)傳來(lái)的文件流代碼實(shí)例
這篇文章主要介紹了Javascript前端下載后臺(tái)傳來(lái)的文件流代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
滾動(dòng)條響應(yīng)鼠標(biāo)滑輪事件實(shí)現(xiàn)上下滾動(dòng)的js代碼
javascript實(shí)現(xiàn)滾動(dòng)條響應(yīng)鼠標(biāo)滑輪的實(shí)現(xiàn)上下滾動(dòng),示例代碼如下2014-06-06
jQuery鼠標(biāo)懸浮鏈接彈出跟隨圖片實(shí)例代碼
這篇文章主要介紹了jQuery鼠標(biāo)懸浮鏈接彈出跟隨圖片實(shí)例代碼,需要的朋友可以參考下2016-01-01
使用ef6創(chuàng)建oracle數(shù)據(jù)庫(kù)的實(shí)體模型遇到的問(wèn)題及解決方案
這篇文章主要介紹了使用ef6創(chuàng)建oracle數(shù)據(jù)庫(kù)的實(shí)體模型遇到的問(wèn)題及解決方案,需要的朋友可以參考下2017-11-11

