Why underscorenode
最近開始看 underscore.js 源碼,並將 underscore.js 源碼解讀 放在了個人 2016 計劃中。git
閱讀一些著名框架類庫的源碼,就好像和一個個大師對話,你會學到不少。爲何是 underscore?最主要的緣由是 underscore 簡短精悍(約 1.5k 行),封裝了 100 多個有用的方法,耦合度低,很是適合逐個方法閱讀,適合樓主這樣的 JavaScript 初學者。從中,你不只能夠學到用 void 0 代替 undefined 避免 undefined 被重寫等一些小技巧 ,也能夠學到變量類型判斷、函數節流&函數去抖等經常使用的方法,還能夠學到不少瀏覽器兼容的 hack,更能夠學到做者的總體設計思路以及 API 設計的原理(向後兼容)。github
以後樓主會寫一系列的文章跟你們分享在源碼閱讀中學習到的知識。數組
underscore-1.8.3 源碼全文註釋 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/underscore-1.8.3-analysis.js瀏覽器
underscore-1.8.3 源碼解讀項目地址 https://github.com/hanzichi/underscore-analysis框架
歡迎圍觀~ (若是有興趣,歡迎 star & watch~)您的關注是樓主繼續寫做的動力ide
類型判斷函數
第一篇跟你們簡單地聊了下爲何 underscore.js 用 void 0 代替了 undefined,意外地收到了不錯的反響,有朋友私信我說之前還真不知道這回事,也有人催促我趕忙繼續下一篇解讀文章。今天就跟你們聊一聊 underscore.js 中一些 JavaScript 經常使用類型檢查方法,以及一些工具類的判斷方法。工具
咱們先說個老生常談的問題,JavaScript 中數組類型的判斷方法,事實上,我在 Javascript中判斷數組的正確姿式 一文中已經詳細分析了各類判斷方式的優缺點,並給出了正確的判斷代碼:學習
function isArray(a) { Array.isArray ? Array.isArray(a) : Object.prototype.toString.call(a) === '[object Array]'; }
而 underscore 其實也正是這麼作的:
// Is a given value an array? // Delegates to ECMA5's native Array.isArray // 判斷是否爲數組 _.isArray = nativeIsArray || function(obj) { return toString.call(obj) === '[object Array]'; };
nativeIsArray 正是 ES5 中 Array.isArray 方法,若是支持則優先調用;而 toString 變量就保存了 Object.prototype.toString。
如何判斷對象?underscore 把類型爲 function 和 object 的變量都算做對象,固然得除去 null。
// Is a given variable an object? // 判斷是否爲對象 // 這裏的對象包括 function 和 object _.isObject = function(obj) { var type = typeof obj; return type === 'function' || type === 'object' & !!obj; };
再看 ‘Arguments’, ‘Function’, ‘String’, ‘Number’, ‘Date’, ‘RegExp’, ‘Error’ 這些類型的判斷,其實均可以用 Object.prototype.toString.call 來判斷,因此寫在了一塊兒:
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. // 其餘類型判斷 _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { _['is' + name] = function(obj) { return toString.call(obj) === '[object ' + name + ']'; }; });
可是看 isArguments 方法,在 IE
// Define a fallback version of the method in browsers (ahem, IE // there isn't any inspectable "Arguments" type. // _.isArguments 方法在 IE // IE // 結果是 [object Object] // 而並不是咱們指望的 [object Arguments]。 // so 用是否含有 callee 屬性來判斷 if (!_.isArguments(arguments)) { _.isArguments = function(obj) { return _.has(obj, 'callee'); }; }
工具類判斷方法
接下來看下一些經常使用的工具類判斷方法。
判斷一個元素是不是 DOM 元素,很是簡單,只須要保證它不爲空,且 nodeType 屬性爲 1:
// Is a given value a DOM element? // 判斷是否爲 DOM 元素 _.isElement = function(obj) { // 確保 obj 不是 null // 而且 obj.nodeType === 1 return !!(obj & obj.nodeType === 1); };
如何判斷一個元素爲 NaN?NaN 實際上是屬於 Number 類型,Object.prototype.toString.call(NaN) 返回的是 「[object Number]」,並且 NaN 不等於自己,利用這兩點便可進行判斷:
// Is the given value `NaN`? (NaN is the only number which does not equal itself). // 判斷是不是 NaN // NaN 是惟一的一個 `本身不等於本身` 的 number 類型 _.isNaN = function(obj) { return _.isNumber(obj) & obj !== +obj; };
固然,underscore 還有不少其餘的有用的工具類判斷方法,具體能夠看源碼 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L1192-L1263 這部分。
若是您以爲我分享的東西對您有所幫助,請關注個人 Repo https://github.com/hanzichi/underscore-analysis