很早就想研究underscore源碼了,雖然underscore.js這個庫有些過期了,可是我仍是想學習一下庫的架構,函數式編程以及經常使用方法的編寫這些方面的內容,又剛好沒什麼其它要研究的了,因此就告終研究underscore源碼這一心願吧。html
underscore.js源碼研究(1)
underscore.js源碼研究(2)
underscore.js源碼研究(3)
underscore.js源碼研究(4)
underscore.js源碼研究(5)
underscore.js源碼研究(6)
underscore.js源碼研究(7)
underscore.js源碼研究(8)node
參考資料:underscore.js官方註釋,undersercore 源碼分析,undersercore 源碼分析 segmentfaultgit
對於類型判斷,大部分元素能夠經過Object.prototype.toString的結果進行判斷,包括:Arguments, Function, String, Number, Date, RegExp, Symbol, Map, WeakMap, Set, WeakSet。實例以下:正則表達式
//判斷是否爲函數,判斷其餘的只要把下面的Function改爲其它的就能夠了 function isFunction (obj) { return Object.prototype.toString.call(obj) === '[object Function]'; } //創建一個函數 var haha = function haha() { consolog.log('haha'); } console.log(isFunction(haha)); //輸出true console.log(isFunction(123)); //輸出false
注意,IE9 之前的版本以及早期 V8 引擎對類型判斷有一些小bug,underscore.js修復了這些問題,具體可自行查看underscore.js源碼。編程
判斷是否爲DOM節點,使用nodeType屬性:segmentfault
function isElement(obj) { return !!(obj && obj.nodeType === 1); }
判斷是否爲數組,優先使用Array.isArray,不支持則使用Object.prototype.toStringapi
var isArray = Array.isArray || function(obj) { return Object.prototype.toString.call(obj) === '[object Array]'; }
使用typeof來判斷是否爲對象。數組
function isObject(obj) { var type = typeof obj; return type === 'function' || type ==='object' && !!obj; }
能夠看到,函數會被判斷爲對象,空對象{},undefined,null,NaN 等則不被認爲是對象。架構
判斷是否有限。主要是使用js全局提供的isFinite函數來判斷。函數式編程
function isFinite(obj) { return !_.isSymbol(obj) && isFinite(obj) && !isNaN(parseFloat(obj)); }
最後那個!isNaN(parseFloat(obj))是爲了排除bool值。
判斷是否爲NaN,主要經過js全局提供的isNaN來判斷。
function isNaN(obj) { return _.isNumber(obj) && isNaN(obj); }
判斷是否爲Boolean。
function isBoolean(obj) { return obj === true || obj === false || Object.prototype.toString.call(obj) === '[object Boolean]'; }
判斷是不是null,直接判斷便可。
function isNull(obj) { return obj === null; }
判斷是不是undefined,利用void 0。
function isUndefined(obj) { return obj === void 0; }
不少時候咱們都要判斷2個元素的相等性,在這個時候咱們能夠先判斷它們的類型,而後再判斷它們的值。能夠有一些特殊的狀況:
它們的解決方案以下:
這裏我不打算寫通常的比較狀況,只是把幾個特殊的狀況寫一下:
主要是轉化爲字符串再比較
Eq = function(a, b) { if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) return false; return '' + a === '' + b; }
須要排除0和NaN的狀況,而且利用+a把a轉化爲數字。
Eq = function(a, b) { if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) return false; return +a === 0 ? 1 / +a === 1 / b : +a === +b; }
利用+a把a轉化爲數字。
Eq = function(a, b) { if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) return false; return +a === +b; }
利用SymbolProto.valueOf方法。
Eq = function(a, b) { if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) return false; return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b); }
注意:不能直接用'=='或者'==='來判斷對象的相等性,緣由以下:
var a = new Object(); var b = new Object(); a.name = "mm"; b.name = "mm"; console.log(a == b); //false