【underscore.js 源碼解讀】常用類(lèi)型判斷以及一些有用的工具方法

Why underscore

最近開(kāi)始看 underscore.js 源碼氏淑,并將 underscore.js 源碼解讀 放在了我的 2016 計(jì)劃中。

閱讀一些著名框架類(lèi)庫(kù)的源碼,就好像和一個(gè)個(gè)大師對(duì)話,你會(huì)學(xué)到很多爽蝴。為什么是 underscore?最主要的原因是 underscore 簡(jiǎn)短精悍(約 1.5k 行)纫骑,封裝了 100 多個(gè)有用的方法蝎亚,耦合度低,非常適合逐個(gè)方法閱讀先馆,適合樓主這樣的 JavaScript 初學(xué)者发框。從中,你不僅可以學(xué)到用 void 0 代替 undefined 避免 undefined 被重寫(xiě)等一些小技巧 煤墙,也可以學(xué)到變量類(lèi)型判斷梅惯、函數(shù)節(jié)流&函數(shù)去抖等常用的方法宪拥,還可以學(xué)到很多瀏覽器兼容的 hack,更可以學(xué)到作者的整體設(shè)計(jì)思路以及 API 設(shè)計(jì)的原理(向后兼容)铣减。

之后樓主會(huì)寫(xiě)一系列的文章跟大家分享在源碼閱讀中學(xué)習(xí)到的知識(shí)她君。

歡迎圍觀~ (如果有興趣,歡迎 star & watch~)您的關(guān)注是樓主繼續(xù)寫(xiě)作的動(dòng)力

類(lèi)型判斷

第一篇跟大家簡(jiǎn)單地聊了下為什么 underscore.js 用 void 0 代替了 undefined葫哗,意外地收到了不錯(cuò)的反響缔刹,有朋友私信我說(shuō)以前還真不知道這回事,也有人催促我趕緊繼續(xù)下一篇解讀文章劣针。今天就跟大家聊一聊 underscore.js 中一些 JavaScript 常用類(lèi)型檢查方法校镐,以及一些工具類(lèi)的判斷方法。

我們先說(shuō)個(gè)老生常談的問(wèn)題捺典,JavaScript 中數(shù)組類(lèi)型的判斷方法鸟廓,事實(shí)上,我在 Javascript中判斷數(shù)組的正確姿勢(shì) 一文中已經(jīng)詳細(xì)分析了各種判斷方式的優(yōu)缺點(diǎn)襟己,并給出了正確的判斷代碼:

function isArray(a) {
  Array.isArray ? Array.isArray(a) : Object.prototype.toString.call(a) === '[object Array]';
}

而 underscore 其實(shí)也正是這么做的:

// Is a given value an array?
// Delegates to ECMA5's native Array.isArray
// 判斷是否為數(shù)組
_.isArray = nativeIsArray || function(obj) {
  return toString.call(obj) === '[object Array]';
};

nativeIsArray 正是 ES5 中 Array.isArray 方法肝箱,如果支持則優(yōu)先調(diào)用;而 toString 變量就保存了 Object.prototype.toString稀蟋。

如何判斷對(duì)象煌张?underscore 把類(lèi)型為 function 和 object 的變量都算作對(duì)象,當(dāng)然得除去 null退客。

// Is a given variable an object?
// 判斷是否為對(duì)象
// 這里的對(duì)象包括 function 和 object
_.isObject = function(obj) {
  var type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

再看 'Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error' 這些類(lèi)型的判斷骏融,其實(shí)都可以用 Object.prototype.toString.call 來(lái)判斷,所以寫(xiě)在了一起:

// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
// 其他類(lèi)型判斷
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
  _['is' + name] = function(obj) {
    return toString.call(obj) === '[object ' + name + ']';
  };
});

但是看 isArguments 方法萌狂,在 IE < 9 下對(duì) arguments 調(diào)用 Object.prototype.toString.call档玻,結(jié)果是 [object Object],而并非我們期望的 [object Arguments]茫藏。咋整误趴?我們可以用該元素是否含有 callee 屬性來(lái)判斷,眾所周時(shí)务傲,arguments.callee 能返回當(dāng)前 arguments 所在的函數(shù)凉当。

// Define a fallback version of the method in browsers (ahem, IE < 9), where
// there isn't any inspectable "Arguments" type.
// _.isArguments 方法在 IE < 9 下的兼容
// IE < 9 下對(duì) arguments 調(diào)用 Object.prototype.toString.call 方法
// 結(jié)果是 [object Object]
// 而并非我們期望的 [object Arguments]。
// so 用是否含有 callee 屬性來(lái)判斷
if (!_.isArguments(arguments)) {
  _.isArguments = function(obj) {
    return _.has(obj, 'callee');
  };
}

工具類(lèi)判斷方法

接下來(lái)看下一些常用的工具類(lèi)判斷方法售葡。

判斷一個(gè)元素是否是 DOM 元素看杭,非常簡(jiǎn)單,只需要保證它不為空挟伙,且 nodeType 屬性為 1:

// Is a given value a DOM element?
// 判斷是否為 DOM 元素
_.isElement = function(obj) {
  // 確保 obj 不是 null 
  // 并且 obj.nodeType === 1
  return !!(obj && obj.nodeType === 1);
};

如何判斷一個(gè)元素為 NaN楼雹?NaN 其實(shí)是屬于 Number 類(lèi)型,Object.prototype.toString.call(NaN) 返回的是 "[object Number]",而且 NaN 不等于本身贮缅,利用這兩點(diǎn)即可進(jìn)行判斷:

// Is the given value `NaN`? (NaN is the only number which does not equal itself).
// 判斷是否是 NaN
// NaN 是唯一的一個(gè) `自己不等于自己` 的 number 類(lèi)型
_.isNaN = function(obj) {
  return _.isNumber(obj) && obj !== +obj;
};

當(dāng)然榨咐,underscore 還有很多其他的有用的工具類(lèi)判斷方法,具體可以看源碼 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L1192-L1263 這部分谴供。

如果您覺(jué)得我分享的東西對(duì)您有所幫助块茁,請(qǐng)關(guān)注我的 Repo https://github.com/hanzichi/underscore-analysis

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市憔鬼,隨后出現(xiàn)的幾起案子龟劲,更是在濱河造成了極大的恐慌胃夏,老刑警劉巖轴或,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異仰禀,居然都是意外死亡照雁,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)答恶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)饺蚊,“玉大人,你說(shuō)我怎么就攤上這事悬嗓∥酆簦” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵包竹,是天一觀的道長(zhǎng)燕酷。 經(jīng)常有香客問(wèn)我,道長(zhǎng)周瞎,這世上最難降的妖魔是什么苗缩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮声诸,結(jié)果婚禮上酱讶,老公的妹妹穿的比我還像新娘。我一直安慰自己彼乌,他們只是感情好泻肯,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著慰照,像睡著了一般软免。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上焚挠,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天膏萧,我揣著相機(jī)與錄音,去河邊找鬼。 笑死榛泛,一個(gè)胖子當(dāng)著我的面吹牛蝌蹂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播曹锨,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼孤个,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了沛简?” 一聲冷哼從身側(cè)響起齐鲤,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎椒楣,沒(méi)想到半個(gè)月后给郊,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捧灰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年淆九,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毛俏。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡炭庙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出煌寇,到底是詐尸還是另有隱情焕蹄,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布阀溶,位于F島的核電站腻脏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏淌哟。R本人自食惡果不足惜迹卢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望徒仓。 院中可真熱鬧腐碱,春花似錦、人聲如沸掉弛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)殃饿。三九已至谋作,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乎芳,已是汗流浹背遵蚜。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工帖池, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吭净。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓睡汹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親寂殉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子囚巴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容