lodash源碼收穫之bitmarks

文章原由

近期由於函數式編程的curry開始了lodash的源碼閱讀,結果開開頭就看到了這樣的代碼javascript

var WRAP_BIND_FLAG = 1,
      WRAP_BIND_KEY_FLAG = 2,
      WRAP_CURRY_BOUND_FLAG = 4,
      WRAP_CURRY_FLAG = 8,
      WRAP_CURRY_RIGHT_FLAG = 16,
      WRAP_PARTIAL_FLAG = 32,
      WRAP_PARTIAL_RIGHT_FLAG = 64,
      WRAP_ARY_FLAG = 128,
      WRAP_REARG_FLAG = 256,
      WRAP_FLIP_FLAG = 512;

程序員就不用說了,什麼2,4,8,16,這樣的數列一看就知道是什麼東西.前端

而後我在curry函數裏面發現這個函數主要是由一個 createWrap的函數 實現, 而後我又進入了這個函數,發現裏面有這麼些代碼java

var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
    
    bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);

這裏面有個按位與操做,如果沒學過其餘語言,直接上手javascript 的程序員 估計 會不知道這些基礎知識,我是java轉的前端,雖然java學得不怎麼樣,可是這些東西我一看就知道是什麼,可是我不知道,這些操做在幹什麼,也不知道爲何要這麼作,因而就開始了個人求知之旅.程序員

lodash 做者在 那一段 標記聲明語句的上面 寫了這麼一個註釋 編程

/* Used to compose bitmasks for function metadata. /函數式編程

bitmasks 對我來講但是一個新詞.....函數

bitmasks是啥

程序猿都知道,有些操做要判斷他是什麼狀態才執行,什麼狀態不執行.性能

那麼咱們就須要一些標記來幫助咱們來肯定,他是什麼狀態的.狀態可不止 true false 這麼簡單.google

bitmasks 就是用來標記狀態的,只不過他是用位操做的方式來標記.code

爲何要用 bitmasks

相信你們寫過這樣的狀態,好比程序員的擼碼和寫文章狀態.

var NO_Status = 0;
var CODING = 1;
var WRITING = 2;

咱們能夠在上面的狀態中切換,咱們設置狀態的時候能夠這樣設置.

var NOW_STATUS = CODING;
if (NOW_STATUS === CODING) {
    // todo
}

當咱們要清楚狀態的時候 咱們又要從新取消狀態;

若是咱們的狀態須要組合,好比我如今一邊寫文章,一邊擼碼,那麼咱們是否要定義多一個狀態,來知足咱們的需求呢?

學過排列與組合的就知道,當狀態越多的時候,組合是成次方增加的.(意思就是,定義到你撲街---手抽筋)

bitmarks 如何使用

若是使用bitmasks 狀態就會變成下面這樣,參考 lodash 源碼

var NO_Status = 0;
var CODING = 2;
var WRITING = 4;

那麼,如今咱們設置狀態還用 a = b 這種形式嗎,既然使用了 bitmarks 那就要體現出這個 bit 呀

如今咱們這樣設置狀態

var NOW_STATUS |= CODEING

二進制就再也不這裏跟你們說了,程序員必備知識

這裏用8位來演示,16 32 也不過是多幾個0而已

NOW_STATUS: 0000 0000
CODEING: 0000 0010
按位或操做 同位兩個數任意一個是1 結果就爲1
獲得 0000 0010 如此狀態設置成功

| 按位或操做是放大操做, 也就獲得的數會比兩個都大,若是前面的值是0,後面的值大於0, 那麼獲得的結果就是後者的自己,如此就設置了CODEING的 狀態 可用於 爲true 時執行的判斷;

如果咱們要消除這個狀態,普通作法是從新賦值爲NO_STATUS,如今咱們這樣作.

var NOW_STATUS &= ~(CODEING)

與是縮小操做,把CODEING 按位非之後........ 說個蛇皮怪,按位操做本身百度去.

這裏只解釋緣由, 爲何要按位非,咱們用按位或操做 設置了值,若是咱們要返回去,那麼咱們必需要按位與纔可以返回去,由於一個爲放大操做,一個爲縮小操做,那麼咱們怎麼才能返回去呢,按位與操做 相同位只要有一個0 那麼結果位就是0 那麼簡單了 咱們只要把原來放大的數的相同位的1變回0 那不就能夠了嘛 在 按位操做中,~ 就是這樣的操做,就像這樣 2 是 0000 0010 按位非後 1111 1101 在於 0000 0010 按位與 我去 變成0000 0000 了,看這不是回去了嘛;

那我如何知道我在那個狀態

若是兩個大於0的相同的數 按位與,結果會返回原來的數

就像這樣,

NOW_STATUS & CODEING > 0 那麼就能夠肯定你再哪一個狀態了

那麼若是個人狀態要組合呢? 就是這兩個參數均可以 還須要從新定義一些狀態嗎, 天真,看個人

var NOW_STATUS= CODEING | WRITING

nor! 狀態出來了, 並且極具可讀性, 一看就知道我 一邊CODEING 一邊 WRITING , 又多了一個請用一邊...一邊...造句的例子

解釋:

2 | 4 對比 返回的是6 任何兩個不同的數相或 ,都不會有重複的,所以 只要你定義狀態的時候 符合 1,2,4,8,16,32 這樣的規律你就不會擔憂狀態值相等;

那麼如何肯定我在這兩個狀態之一呢?

這樣

NOW_STATUS & (CODEING | WRITING) != 0

嗯哼? OJBK
解釋: 對應上面代碼 6 & (2 | 4) != 0
6 & 4 = 4, 6 & 2 = 2, 都大於0 看判斷成功;

bitmarks 的好處

其實在爲何要用bitmarks 的時候 出現的都是 bitmarks 的好處

可是還有同樣, 就是性能, 咱們知道內存中數字都是2進制存的, 那麼咱們操做數字的時候使用2進制的方式操做,可以節省掉那麼一絲的系統資源,螞蟻雖小也是肉呀

lodash 真是個好東西, 雖然我不怎麼用,可是裏面的基礎和思想,是我想要的東西.

最後

我會繼續閱讀,有我能駕馭的,必定再寫一些東西分享出來.

參考文獻:

google 搜索 : bitmarks 前3個 哈哈哈哈哈哈哈哈哈

相關文章
相關標籤/搜索