js中表達式 >>> 0 淺析

今天在看lodash的源碼中slice這個函數實現的時候發現了裏面有這麼一行代碼javascript

length = start > end ? 0 : ((end - start) >>> 0)
start >>>= 0

當時就很疑惑,知道 >>是移位,那>>>又是什麼鬼,還有移位0位又有什麼意義呢,帶着強烈的好奇心,我就去探究了一下 >>> 0它到底暗藏什麼玄機。html

  • >>>>>有什麼不同

查了MDN原來>>>是無符號右移,>>是有符號移位,
>>有符號移位:該操做符會將第一個操做數向右移動指定的位數。向右被移出的位被丟棄,拷貝最左側的位以填充左側java

-9 >> 2
11111111111111111111111111110111  // -9 -> 11111111111111111111111111111101   // -3

>>>無符號移位:該操做符會將第一個操做數向右移動指定的位數。向右被移出的位被丟棄,左側用0填充。由於符號位變成了 0,因此結果老是非負的。(即使右移 0 個比特,結果也是非負的。git

9 >>> 2
00000000000000000000000000001001   // 9 ->  00000000000000000000000000000010 // 2

根據文檔說明即便移動0位也能夠將一個負數變成正數,甚至也能夠將一個小數變成整數,將未定義的值轉換爲0,那到底移動0位是什麼意思。github

  • 移位0有什麼意義

查過一些資料,其中stackoverflow裏面有一個高票回答,裏面有這麼一句話express

It doesn't just convert non-Numbers to Number, it converts them to Numbers that can be expressed as 32-bit unsigned ints.

原來移位操做符在移位前作了兩種轉換,第一將不是number類型的數據轉換爲number,第二將number轉換爲無符號的32bit數據,也就是Uint32類型。這些與移位的位數無關,移位0位主要就是用了js的內部特性作了前兩種轉換。數組

  • Uint32類型是如何轉換的

1 . 若是不能轉換爲Number,那就爲0
2 . 若是爲非整數,先轉換爲整數,參考公式sign(n) ⋅ floor(abs(n))函數

function ToInteger(x) {
    x = Number(x);
    return x < 0 ? Math.ceil(x) : Math.floor(x);
}

3 . 若是是正數,返回正數,若是是負數,返回負數 + 2的32次方code

function modulo(a, b) {
    return a - Math.floor(a/b)*b;
}
function ToUint32(x) {
    return modulo(ToInteger(x), Math.pow(2, 32));
}

參考文章 Integers and shift operators in JavaScripthtm

  • 總結

x >>> 0本質上就是保證x有意義(爲數字類型),且爲正整數,在有效的數組範圍內(0 ~ 0xFFFFFFFF),且在無心義的狀況下缺省值爲0。一個小小的表達式,隱藏着着多重的異常處理。js真是詭異啊。

相關文章
相關標籤/搜索