成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【underscore 源碼解讀】JavaScript 中如何判斷兩個元素是否 "相同&q

yhaolpz / 3219人閱讀

摘要:最近開始看源碼,并將源碼解讀放在了我的計劃中。后文中均假設(shè)比較的兩個參數(shù)為和。,如果和均是類型或者類型,我們可以用來判斷是否。

Why underscore

最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。

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

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

underscore-1.8.3 源碼解讀項(xiàng)目地址 https://github.com/hanzichi/underscore-analysis

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/issues

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

_.isEqual

本文跟大家聊聊 JavaScript 中如何判斷兩個參數(shù) "相同",即 underscore 源碼中的 _.isEqual 方法。這個方法可以說是 underscore 源碼中實(shí)現(xiàn)最復(fù)雜的方法(用了百來行),幾乎沒有之一。

那么,我說的 "相同" 到底是什么意思?舉個栗子,1new Number(1) 被認(rèn)為是 equal,[1][1] 被認(rèn)為是 equal(盡管它們的引用并不相同),當(dāng)然,兩個引用相同的對象肯定是 equal 的了。

那么,如何設(shè)計這個 _.isEqual 函數(shù)呢?我們跟著 underscore 源碼,一步步來看它的實(shí)現(xiàn)。后文中均假設(shè)比較的兩個參數(shù)為 a 和 b。

首先我們判斷 a === b,為 true 的情況有兩種,其一是 a 和 b 都是基本類型,那么就是兩個基本類型的值相同,其二就是兩個引用類型,那么就是引用類型的引用相同。那么如果 a === b 為 true,是否就是說 a 和 b 是 equal 的呢?事實(shí)上,99% 的情況是這樣的,還得考慮 0 和 -0 這個 special case,0 === -0 為 true,而 0 和 -0 被認(rèn)為是 unequal,至于原因,可以參考 http://wiki.ecmascript.org/doku.php?id=harmony:egal。

這部分代碼可以這樣表示:

// Identical objects are equal. `0 === -0`, but they aren"t identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
// a === b 時
// 需要注意 `0 === -0` 這個 special case
// 0 和 -0 不相同
// 至于原因可以參考上面的鏈接
if (a === b) return a !== 0 || 1 / a === 1 / b;

接下去的情況,也就是 a !== b 的情況了。

如果 a 和 b 中有一個是 null 或者 undefined,那么可以特判下,不用繼續(xù)比較了。源碼實(shí)現(xiàn):

// A strict comparison is necessary because `null == undefined`.
// 如果 a 和 b 有一個為 null(或者 undefined)
// 判斷 a === b
if (a == null || b == null) return a === b;

個人覺得這里寫的有點(diǎn)多余,因?yàn)楦鶕?jù)上面的判斷過濾,a === b 肯定是返回 false 的。

ok,我們繼續(xù),接下來我們可以先根據(jù) a 和 b 的類型來判斷,如果類型不一樣,那么就沒必要繼續(xù)判斷了。如何獲取變量類型?沒錯,就是神奇的 Object.prototype.toString.call

如果類型是 RegExp 和 String,我們可以將 a 和 b 分別轉(zhuǎn)為字符串進(jìn)行比較(如果是 String 就已經(jīng)是字符串了),舉個栗子:

var a = /a/;
var b = new RegExp("a");

console.log(_.isEqual(a, b));  // => true

其實(shí)它在 underscore 內(nèi)部是這樣判斷的:

var a = /a/;
var b = new RegExp("a");

var _a = "" + a; // => /a/
var _b = "" + b; // => /a/

console.log(_a === _b); // => true

如果是 Number 類型呢?這里又有個 special case,就是 NaN!這里規(guī)定,NaN 僅和 NaN 相同,與別的 Number 類型均 unequal。這里我們將引用類型均轉(zhuǎn)為基本類型,看如下代碼:

var a = new Number(1);
console.log(+a); // 1

沒錯,加個 + 就解決了,其他的不難理解,都在注釋里了。

// `NaN`s are equivalent, but non-reflexive.
// Object(NaN) is equivalent to NaN
// 如果 +a !== +a 
// 那么 a 就是 NaN
// 判斷 b 是否也是 NaN 即可
if (+a !== +a) return +b !== +b;

// An `egal` comparison is performed for other numeric values.
// 排除了 NaN 干擾
// 還要考慮 0 的干擾
// 用 +a 將 Number() 形式轉(zhuǎn)為基本類型
// 如果 a 為 0,判斷 1 / +a === 1 / b
// 否則判斷 +a === +b
return +a === 0 ? 1 / +a === 1 / b : +a === +b;

// 如果 a 為 Number 類型
// 要注意 NaN 這個 special number
// NaN 和 NaN 被認(rèn)為 equal

接下來我們看 Date 和 Boolean 兩個類型。跟 Number 類型相似,它們也可以用 + 轉(zhuǎn)化為基本類型的數(shù)字!看下面代碼:

var a = new Date();
var b = true;
var c = new Boolean(false);

console.log(+a); // 1464180857222
console.log(+b); // 1
console.log(+c); // 0

非常簡單,其實(shí) +new Date() (或者也可以寫成 +new Date)獲取的正是當(dāng)前時間和 1970 年 1 月 1 日 0 點(diǎn)的毫秒數(shù)(millisecond),可能你聽說過時間戳,其實(shí)時間戳就是這個數(shù)據(jù)除以 1000,也就是秒數(shù)。在用 canvas 做動畫時,我經(jīng)常用 +new Date 來當(dāng)時間戳。

so,如果 a 和 b 均是 Date 類型或者 Boolean 類型,我們可以用 +a === +b 來判斷是否 equal。

程序接著走,我們接著看,似乎還有兩類重要的類型沒有判斷?沒錯,Array 和 Object!underscore 對此采用遞歸方法展開來比較。

還是舉個栗子吧,舉例比較直觀。

假設(shè) a,b 如下:

var a = {name: "hanzichi", loveCity: [{cityName: "hangzhou", province: "zhenjiang"}], age: 30};
var b = {name: "hanzichi", loveCity: [{cityName: "hangzhou", province: "zhenjiang"}], age: 25};

首先 a,b 是對象,我們可以分別比較其鍵值對,如果有一個鍵值對不同(或者說一個鍵值對 a 和 b 有一個沒有),則 a 和 b unequal。如果是數(shù)組呢?那就一個一個元素比較嘍。因?yàn)閿?shù)組可能嵌套對象,對象的 value 又可能是數(shù)組,所以這里用了遞歸。

還是以上面的例子,我們可以把它拆成三次比較,分別比較三個 key 的 value 值是否相同。對于 loveCity 這個 key 的 value,因?yàn)槠?value 又是個數(shù)組,所以我們將這個 value 傳入比較函數(shù),通過這個比較的結(jié)果,來判斷最后的比較結(jié)果。遞歸就是這樣,可以將大的東西,拆成一個個小的,根據(jù)小的結(jié)果,來匯總得到大的結(jié)果。

最后,給出代碼位置。關(guān)于 _.isEqual 方法的源碼,大家可以參考 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L1094-L1190

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79563.html

相關(guān)文章

  • underscore 源碼解讀如何優(yōu)雅地寫一個『在數(shù)組尋找指定元素』的方法

    摘要:今天要講的是,如何在數(shù)組中尋找元素,對應(yīng)中的,,,以及方法。如果往一個有序數(shù)組中插入元素,使得數(shù)組繼續(xù)保持有序,那么這個插入位置是這就是這個方法的作用,有序,很顯然用二分查找即可。 Why underscore (覺得這部分眼熟的可以直接跳到下一段了...) 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一...

    0x584a 評論0 收藏0
  • underscore.js 源碼解讀】常用類型判斷以及一些有用的工具方法

    摘要:最近開始看源碼,并將源碼解讀放在了我的計劃中。今天就跟大家聊一聊中一些常用類型檢查方法,以及一些工具類的判斷方法。用是否含有屬性來判斷工具類判斷方法接下來看下一些常用的工具類判斷方法。 Why underscore 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一些著名框架類庫的源碼,就好像和一個個大師對話...

    tanglijun 評論0 收藏0
  • 也談面試必備問題之 JavaScript 數(shù)組去重

    摘要:而數(shù)組元素去重是基于運(yùn)算符的。而如果有迭代函數(shù),則計算傳入迭代函數(shù)后的值,對值去重,調(diào)用方法,而該方法的核心就是調(diào)用方法,和我們上面說的方法一異曲同工。 Why underscore (覺得這部分眼熟的可以直接跳到下一段了...) 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一些著名框架類庫的源碼,就好像...

    Coly 評論0 收藏0
  • underscore.js 源碼解讀】for ... in 存在的瀏覽器兼容問題你造嗎

    摘要:最近開始看源碼,并將源碼解讀放在了我的計劃中。像和使用內(nèi)置構(gòu)造函數(shù)所創(chuàng)建的對象都會繼承自和的不可枚舉屬性,例如的方法或者的方法。循環(huán)將迭代對象的所有可枚舉屬性和從它的構(gòu)造函數(shù)的繼承而來的包括被覆蓋的內(nèi)建屬性。 Why underscore 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一些著名框架類庫的源碼...

    Pikachu 評論0 收藏0
  • JavaScript專題系列文章

    摘要:專題系列共計篇,主要研究日常開發(fā)中一些功能點(diǎn)的實(shí)現(xiàn),比如防抖節(jié)流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點(diǎn)是研究專題之函數(shù)組合專題系列第十六篇,講解函數(shù)組合,并且使用柯里化和函數(shù)組合實(shí)現(xiàn)模式需求我們需要寫一個函數(shù),輸入,返回。 JavaScript 專題之從零實(shí)現(xiàn) jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實(shí)現(xiàn)一個 jQuery 的 ext...

    Maxiye 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<