underscore源碼解讀系列之一--underscore的一些工具函數

首先看一些在object塊定義的經常使用的類型判斷函數。node

_.isElement(object)

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

nodeType相關知識點:git

節點類型 描述 名稱
1 Element 元素 ELEMENT_NODE
2 Attr 屬性 ATTRIBUTE_NODE
3 Text 文本內容 TEXT_NODE
8 Comment 註釋 COMMENT_NODE
9 Document 整個文檔(DOM)樹的根節點 DOCUMENT_NODE
11 DocumentFragment 某個文檔片斷 DOCUMENT_FRAGMENT_NODE

其實通常來講是會隱式轉換的...可能這裏是在強制轉換避免出錯吧。github

_.isArray(object)

_.isArray = nativeIsArray || function(obj) {
    return toString.call(obj) === '[object Array]';
};

吶吶...underscore的開頭就引用了js原生的一些方法:正則表達式

var ArrayProto = Array.prototype, 
    ObjProto = Object.prototype,
    FuncProto = Function.prototype;

var push             = ArrayProto.push,
    slice            = ArrayProto.slice,
    toString         = ObjProto.toString,
    hasOwnProperty   = ObjProto.hasOwnProperty;

var nativeIsArray    = Array.isArray,
    nativeKeys       = Object.keys,
    nativeBind       = FuncProto.bind,
    nativeCreate     = Object.create;

而關於[object Array]...數組

當判斷一個對象是否爲數組時,不能用typeof運算符進行操做,由於會返回object函數

typeof([]) // "object"

那這個時候怎麼判斷數組是否是數組呢...雖然如今有原生的isArray來判斷:spa

Array.isArray([]) // true

可是依然存在一種調用object的toString()方法來判斷的辦法:prototype

Object.prototype.toString.call([]) // "[object Array]"

這個辦法還能夠用來判斷別的各類類型:code

_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
    _['is' + name] = function(obj) {
        return toString.call(obj) === '[object ' + name + ']';
    };
});

_.each方法以後會細說,當作原生的forEach來看吶。對象

_.isObject(value)

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

嗯...這裏要注意的是運算符的優先級,&&優先級高於||,因此這裏把函數也做爲object來看待了...

_.isObject(function f() {}) // true

_.isArguments(object)

if (!_.isArguments(arguments)) {
    _.isArguments = function(obj) {
        return _.has(obj, 'callee');
    };
}

由於IE<9下對arguments調用Object.prototype.toString.call(),返回的是[object Object],而非[object Arguments],因此遇到這種狀況須要判斷一下是否還有callee屬性。

_.isFunction(object)

if (typeof /./ != 'function' && typeof Int8Array != 'object') {
    _.isFunction = function(obj) {
        return typeof obj === 'function' || false;
    };
}

Safari5及以前版本、Chrome7及以前版本在對正則表達式調用typeof操做符時會返回function,因此就是爲了功能兼容吧。

_.isFinite(object)

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

用到了JavaScript的全局函數isFinite,會檢查參數是否爲無窮大。

isFinite(function f() {}) // false,由於值爲NaN
isFinite(123) // true

_.isNaN(object)

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

首先判斷是否爲數字,其次判斷其自己是否與本身相等。

嗯,這是隻針對數字的判斷。

還有這樣一個bug...???

_.isBoolean(object)

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

其實我感受可能直接用toString.call(obj) === '[object Boolean]'就能夠...

_.isNull(object)和_.isUndefined(value)

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

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

這裏就涉及到了爲何用void 0而不是undefined

在非嚴格模式下,咱們能夠爲全局標識符undefined賦值

--《你不知道的js》

可是我沒運行出來。並且嚴格模式下也沒有報錯...

function foo() {
    undefined = 2
}
console.log(undefined) // undefined

能夠聲明一個名爲undefined的局部變量卻是真的。

function foo() {
    var undefined = 2
    console.log(undefined) // 2
}
foo()

因此說明使用undefined不少時候是不靠譜的。

void 0呢,表達式void沒有返回值,所以返回結果是undefinedvoid並不改變表達式的結果,只是讓表達式不返回值。在這個層面上講,void 0void a都是同樣的。

var obj = {a: 3}
void obj // undefined

_.isEmpty(object)

_.isEmpty = function(obj) {
    if (obj === null) return true;

    if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) 
        return obj.length === 0;

    return _.keys(obj).length === 0;
};

判斷是否爲空的方法:

  • 若是是null,則爲空;
  • 若是是有長度的結構(數組,類數組,字符串等),則判斷其長度;
  • 若是是object,則判斷由key組成的數組的長度~

_.has(obj, key)

_.has = function(obj, key) {
    return obj != null && hasOwnProperty.call(obj, key);
  };

首先要肯定傳入的對象不能爲空,而後用hasOwnProperty來檢查是否爲對象的屬性。

相關文章
相關標籤/搜索