国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

yhaolpz / 3217人閱讀

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

Why underscore

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

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

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

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ù)寫作的動(dòng)力

_.isEqual

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

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

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

首先我們判斷 a === b,為 true 的情況有兩種,其一是 a 和 b 都是基本類型,那么就是兩個(gè)基本類型的值相同,其二就是兩個(gè)引用類型,那么就是引用類型的引用相同。那么如果 a === b 為 true,是否就是說 a 和 b 是 equal 的呢?事實(shí)上,99% 的情況是這樣的,還得考慮 0 和 -0 這個(gè) 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 時(shí)
// 需要注意 `0 === -0` 這個(gè) special case
// 0 和 -0 不相同
// 至于原因可以參考上面的鏈接
if (a === b) return a !== 0 || 1 / a === 1 / b;

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

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

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

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

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

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

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

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

沒錯(cuò),加個(gè) + 就解決了,其他的不難理解,都在注釋里了。

// `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 這個(gè) special number
// NaN 和 NaN 被認(rèn)為 equal

接下來我們看 Date 和 Boolean 兩個(gè)類型。跟 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)前時(shí)間和 1970 年 1 月 1 日 0 點(diǎn)的毫秒數(shù)(millisecond),可能你聽說過時(shí)間戳,其實(shí)時(shí)間戳就是這個(gè)數(shù)據(jù)除以 1000,也就是秒數(shù)。在用 canvas 做動(dòng)畫時(shí),我經(jīng)常用 +new Date 來當(dāng)時(shí)間戳。

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

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

還是舉個(gè)栗子吧,舉例比較直觀。

假設(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 是對(duì)象,我們可以分別比較其鍵值對(duì),如果有一個(gè)鍵值對(duì)不同(或者說一個(gè)鍵值對(duì) a 和 b 有一個(gè)沒有),則 a 和 b unequal。如果是數(shù)組呢?那就一個(gè)一個(gè)元素比較嘍。因?yàn)閿?shù)組可能嵌套對(duì)象,對(duì)象的 value 又可能是數(shù)組,所以這里用了遞歸。

還是以上面的例子,我們可以把它拆成三次比較,分別比較三個(gè) key 的 value 值是否相同。對(duì)于 loveCity 這個(gè) key 的 value,因?yàn)槠?value 又是個(gè)數(shù)組,所以我們將這個(gè) value 傳入比較函數(shù),通過這個(gè)比較的結(jié)果,來判斷最后的比較結(jié)果。遞歸就是這樣,可以將大的東西,拆成一個(gè)個(gè)小的,根據(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)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/79563.html

相關(guān)文章

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

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

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

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

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

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

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

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

    Pikachu 評(píng)論0 收藏0
  • JavaScript專題系列文章

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

    Maxiye 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<