後面的程式碼真是越看越難理解,經常需要結合內部/介面函式一起,所以採用跳讀的方式解析,基本按照模組由易到難的順序解析。
1 2 3 |
456 _.initial = function(array, n, guard) { return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); }; |
這個guard引數說是保證預設返回第一個值,不過我看了很久覺得意義不大,猜測可能是以前的介面。這裡的slice = Array.prototype.slice
。這裡有兩個地方比較好,一是用Array的原型函式來處理array引數,這樣可以避免判斷array是否陣列,二是用max來避免超出陣列長度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
671 _.range = function(start, stop, step) { if (arguments.length <= 1) { stop = start || 0; start = 0; } step = step || 1; var length = Math.max(Math.ceil((stop - start) / step), 0); var range = Array(length); for (var idx = 0; idx < length; idx++, start += step) { range[idx] = start; } return range; }; |
這個函式本什沒有什麼特別的,只不過我在呼叫的時候將step賦值為小數,就出現了javascript著名的精度問題。網上應該有不少的解決方案,這裡提供一種目前我在專案中用到的解決方法:將數字轉為字串在去小數點之後轉為整數進行計算,計算完成後轉字串加上小數點再轉成小數,舉個例子
1 2 3 |
1.11 ==> "1.11" ==> "111" ==> 111 2.2 ==> "2.2" ==> "220" ==> 220 111+220 ==> 331 ==> "331" ==> "3.31" ==> 3.31 |
陣列程式碼看得累了,從後面的看起吧~
1 2 3 4 |
1269 _.noConflict = function() { root._ = previousUnderscore; return this; }; |
這個讓渡函式其實原理比較簡單,就是初始化underscore前 previousUnderscore=window._
對原有物件進行儲存,如果需要讓渡避免衝突,則進行還原同時返回當前underscore物件。再來看看JQuery的實現原理:
1 2 3 4 5 6 7 8 9 10 11 |
noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; } |
剛開始看的時候犯2了,函式可以用===
來比較?不是隻能比較簡單的資料物件?呵呵,其實這個是通過引用地址來判斷的,因為之前初始化的時候window.$=JQuery
所以$會指向JQuery的地址,所以可以這樣判斷。後面一個if考慮到JQuery這個變數名也被佔用的時候,也進行讓渡,最後返回JQuery物件。可能是考慮多版本的情況吧~
1 2 3 4 5 6 7 8 9 10 11 12 13 |
1487 _.mixin = function(obj) { _.each(_.functions(obj), function(name) { var func = _[name] = obj[name]; _.prototype[name] = function() { var args = [this._wrapped]; push.apply(args, arguments); return result(this, func.apply(_, args)); }; }); }; // Add all of the Underscore functions to the wrapper object. _.mixin(_); |
這個用於擴充套件underscore自身的介面函式,通過迴圈遍歷物件來淺拷貝物件屬性。這裡考慮到函式的例項化,所以一方面將函式作為內部函式使用,同時擴充套件到prototype屬性上。考慮得比較周全。
1 2 3 4 5 |
1469 _.chain = function(obj) { var instance = _(obj); instance._chain = true; return instance; }; |
這個函式讓underscore支援鏈式呼叫,鏈式呼叫寫起來很美觀,但是除錯略顯不方便。結合之前的程式碼來看,underscore實現鏈式呼叫的基本原理是:將引數快取在內部屬性_wrapped中,呼叫函式時傳入該屬性值,執行後返回當前this指標。直到執行value函式時返回_wraped中的值。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式