underscore.js源碼研究(4)

概述

很早就想研究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源碼編程

isElement

判斷是否爲DOM節點,使用nodeType屬性segmentfault

function isElement(obj) {
    return !!(obj && obj.nodeType === 1);
}

isArray

判斷是否爲數組,優先使用Array.isArray,不支持則使用Object.prototype.toStringapi

var isArray = Array.isArray || function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
}

isObject

使用typeof來判斷是否爲對象。數組

function isObject(obj) {
    var type = typeof obj;
    return type === 'function' || type ==='object' && !!obj;
}

能夠看到,函數會被判斷爲對象,空對象{},undefined,null,NaN 等則不被認爲是對象。架構

isFinite

判斷是否有限。主要是使用js全局提供的isFinite函數來判斷。函數式編程

function isFinite(obj) {
    return !_.isSymbol(obj) && isFinite(obj) && !isNaN(parseFloat(obj));
}

最後那個!isNaN(parseFloat(obj))是爲了排除bool值。

isNaN

判斷是否爲NaN,主要經過js全局提供的isNaN來判斷。

function isNaN(obj) {
    return _.isNumber(obj) && isNaN(obj);
}

is Boolean

判斷是否爲Boolean。

function isBoolean(obj) {
    return obj === true || obj === false || Object.prototype.toString.call(obj) === '[object Boolean]';
}

isNull

判斷是不是null,直接判斷便可。

function isNull(obj) {
    return obj === null;
}

isUndefined

判斷是不是undefined,利用void 0。

function isUndefined(obj) {
    return obj === void 0;
}

相等性判斷

不少時候咱們都要判斷2個元素的相等性,在這個時候咱們能夠先判斷它們的類型,而後再判斷它們的值。能夠有一些特殊的狀況:

  • 0 === -0
  • null == undefined
  • NaN != NaN
  • NaN !== NaN

它們的解決方案以下:

  • 1/0 === 1/0; 1/-0 !== 1/0
  • null === null; null !== undefined;
  • if(a !== a) return b !== b;

這裏我不打算寫通常的比較狀況,只是把幾個特殊的狀況寫一下:

正則表達式和字符串

主要是轉化爲字符串再比較

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;
}

Symbol

利用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
相關文章
相關標籤/搜索