js高手進階之路:underscore原始碼經典(一)

亞里士朱德發表於2015-10-18

underscore 原始碼版本 1.8.2

起因

很多人向我推薦研究js,可以看看一些第三方js類庫的原始碼,而原始碼之中最好解讀也最簡短的就是underscore,它也是我平常比較喜歡的一個庫,因為它價效比高:體積小、能力強。開啟一看,才1000多行,試著讀了一下,確實很值得一看,所以對精彩部分做了一下整理。

閉包

整個函式在一個閉包中,避免汙染全域性變數。通過傳入this(其實就是window物件)來改變函式的作用域。和jquery的自執行函式其實是異曲同工之妙。這種傳入全域性變數的方式一方面有利於程式碼閱讀,另一方面方便壓縮。
underscore寫法:

jquery寫法:

原型賦值

Array,Object,Function這些本質都是函式,獲取函式原型屬性prototype也是為了便於壓縮。簡單解釋一下,如果程式碼中要擴充套件屬性,可能這樣寫

而這種程式碼是不可壓縮的,Object,prototype這些名字改了瀏覽器就不認得了。

但是上面的程式碼中建立了ObjProto之後,源生程式碼經過壓縮之後,ObjProto就可能命名成a變數,那麼原來的程式碼就壓縮成

一個小建議就是凡事一段程式碼被使用兩次以上都建議定義變數(函式),有利於修改和壓縮程式碼。

格式

這種定義的方式省略了多餘的var,格式也美觀,讓我想到了sublime中的一個外掛alignment。

資料判斷

判斷是否為dom,dom的nodeType屬性值為1。這裡用!!強轉為boolean值

判斷是否為陣列。由於Array.isArray函式是ECMAScript 5新增函式,所以為了相容之前的版本,在原生判斷函式不存在的情況下,後面重寫了一個判斷函式。用call函式來改變作用域可以避免當obj沒有toString函式報錯的情況。

判斷是否為物件。先用typeof判斷資料型別。函式也屬於物件,但是由於typeof null也是object,所以用!!obj來區分這種情況。

判斷是否為arguments,很簡單,arguments有個特有屬性callee。

NaN這個值有兩個特點:1.它是一個數;2.不等於它自己。
‘+’放在變數前面一般作用是把後面的變數變成一個數,在這裡已經判斷為一個數仍加上’+’,是為了把var num = new Number()這種沒有值的數字也歸為NaN。

是不是以為如果是布林值不是true就是false?還有第3中情況var b = new Boolean()。b也是布林值。

用void 0來表示undefined,非常有意思的小技巧。不過常用方式還是if(xxx)來判斷是不是undefined。

eq是underscore的一個內建函式,程式碼太長,不貼上了。isEmpty呼叫了這個函式。整個思路由易到難,先用===比較簡單資料,然後用toString來判斷是否相等,最後用遞迴處理複雜的Array、Function和Object物件。

這裡為了區分’+0’和’-0’,因為這兩個數對計算結果是有影響的。

這裡是對簡單物件進行判斷,分為兩類,一類是StringRegExp,這種資料直接toString然後判斷。另一類是NumberDateBoolean,通過轉換成數字判斷。

對於陣列和物件只能用遞迴了,同時用aStack和bStack來暫存遞迴中的子物件。這裡一個小技巧的就是先判斷陣列/屬性的長度,如果不相等可以有效地減少遞迴。

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

js高手進階之路:underscore原始碼經典(一) js高手進階之路:underscore原始碼經典(一)

相關文章