這是一篇記錄學習 underscore v0.0.5 的fragment,以爲有點意思,和你們分享一下。數組
先看_.sortedIndex的源碼,它用來肯定 obj 在 array中的位置(array升序):ide
_.sortedIndex = function(array, obj, iterator) { iterator = iterator || _.identity; var low = 0, high = array.length; while (low < high) { var mid = (low + high) >> 1; iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; } return low; }; _.identity = function(value) {return value};
代碼雖短卻兩個我們不經常使用的姿式:>>
運算符和二分查找。學習
右移運算符的計算規則以下操作系統
int a = 8; int b = a >> 1; // b ?
先將 8 轉化爲二進制數,(在 C 中,32位操做系統下int 類型佔2個字節,即16bit)
0000 0000 0000 1000
總體右移 1 位,高位不足添 0
0000 0000 0000 0100
再將新的二進制數轉化爲十進制獲得 b = 4;code
那麼,代碼 var mid = (low + high) >> 1
mid 變量取值是多少呢?由於好(dou)奇(bi),我做了一點嘗試:underscore
0 >> 1 // 0 1 >> 1 // 0 2 >> 1 // 1 3 >> 1 // 1 4 >> 1 // 2 5 >> 1 // 2 ... 10 >> 1 // 5 11 >> 1 // 5 12 >> 1 // 6 ...
由概括法可得 a >> 1 === parseInt(a / 2)
。這點相信眼尖的同窗早就看出來了。源碼
既然咱們已經知曉mid >> 1 === parseInt((low + high) / 2)
,咱們再來回顧下代碼片斷:it
while (low < high) { var mid = (low + high) >> 1; // (1) iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; // (2) }
(1)咱們已經知曉,mid 取得了一箇中間數值,在(2)中是一個三元運算符,解釋起來,就是用一個有序數組 array 的中間數和目標數進行比較,則若是中間數比目標數小,就只須要比較中間數右側的值,反之亦然。而後繼續循環...io
等價於下面的代碼,由此差距立顯:function
while (low < high) { var mid = (low + high) >> 1; var a = iterator(array[mid]); var b = iterator(obj) if(a == b) { return mid; } else if(a < b) { low = mid + 1; } else { high = mid } }
內容照理說已經講完了,但對於 >>
運算符我仍是有些疑慮。既然有a >> 1 === parseInt(a / 2)
那麼能否假設 a >> 2 === parseInt(a / (2*2))
呢?
0 >> 2 // 0 3 >> 2 // 0 4 >> 2 // 1 7 >> 2 // 1 8 >> 2 // 2 11 >> 2 // 2 12 >> 2 // 3
繼而a >> 3 === parseInt(a / (2*2*2))
,可得a >> n === parseInt(a / (X))
X 爲 2 的 n 次方。
與右移運算符相對的叫左移運算符,記爲 <<
,相信它也不是吃乾飯的。
有了前面的鋪墊,我這裏一步到位,假設有a << n === parseInt(a * (X))
X 爲 2 的 n 次方。簡單驗證下:
1 << 1 // 1*2 = 2 2 << 1 // 2*2 = 4 3 << 2 // 3 * (2*2) = 12 5 << 4 // 5 * (2*2*2*2) = 80 ...
最後的最後,因爲水平有限(你們看出來了,忍住不要笑:-D),文章內容連蒙帶猜,沒有通過特別嚴謹的證實,歡迎拍磚!!!