 與三等號(hào)運(yùn)算符(===)在 JavaScript 相等性檢查中的區(qū)別與選型)
教程文檔【免費(fèi)下載鏈接】30-seconds-of-codeCoding articles to level up your development skills項(xiàng)目地址https://gitcode.com/gh_mirrors/30/30-seconds-of-code點(diǎn)擊查看免費(fèi)下載Object.is()與三等號(hào)運(yùn)算符都是 JavaScript 中常用的相等性檢查手段但二者在NaN與0/-0的處理上存在關(guān)鍵分歧。本文以 30-seconds-of-code 倉(cāng)庫(kù)中 object-is-triple-equals.md 為骨架結(jié)合倉(cāng)庫(kù)內(nèi) equality.md、value-not-equal-to-itself.md 等系列文檔完整講清三種比較方式的差異、Object.is()的底層語(yǔ)義與適用場(chǎng)景幫助你寫出行為可預(yù)期的比較代碼。從相等性運(yùn)算符說(shuō)起、與Object.is()在 JavaScript 中判斷兩個(gè)值是否相等開(kāi)發(fā)者最先接觸到的通常是兩個(gè)運(yùn)算符雙等號(hào)與三等號(hào)。正如倉(cāng)庫(kù)中的 equality.md 所總結(jié)的雙等號(hào)也稱寬松相等運(yùn)算符loose equality operator會(huì)對(duì)操作數(shù)進(jìn)行類型強(qiáng)制轉(zhuǎn)換type coercion使兩側(cè)操作數(shù)先轉(zhuǎn)換為同一類型再比較結(jié)果值三等號(hào)也稱嚴(yán)格相等運(yùn)算符strict equality operator同時(shí)比較類型與值不會(huì)做任何隱式類型轉(zhuǎn)換。也就是說(shuō)只關(guān)心值是否相等而嚴(yán)格要求類型與值都相等。在 equality.md 的示例中0 0為true字符串被轉(zhuǎn)換成了數(shù)字而0 0為false類型不同undefined null為true而undefined null為false。正因如此倉(cāng)庫(kù)文檔給出的推薦是絕大多數(shù)場(chǎng)景使用除非你完全確定需要對(duì)操作數(shù)做類型強(qiáng)制轉(zhuǎn)換。然而嚴(yán)格相等之外JavaScript 還提供了第三種選擇——Object.is()。它與在絕大多數(shù)情況下行為完全一致唯一例外是NaN與0/-0這兩類特殊數(shù)值。這正是 object-is-triple-equals.md 要講清楚的核心。Object.is()與的兩個(gè)關(guān)鍵分歧嚴(yán)格相等運(yùn)算符與Object.is()的差異可以歸結(jié)為兩條規(guī)則NaN的自等性NaN NaN為false而Object.is(NaN, NaN)為true零的符號(hào)區(qū)分0 -0為true而Object.is(0, -0)為false。這兩條規(guī)則來(lái)源于 ECMAScript 規(guī)范中的兩種抽象相等性比較算法實(shí)現(xiàn)的是Strict Equality ComparisonSameValueZero 相關(guān)而Object.is()實(shí)現(xiàn)的是SameValue 算法。在其余所有情況下對(duì)象引用、字符串、布爾值、普通數(shù)值、undefined、null等二者給出的結(jié)果完全一致。逐例拆解用代碼驗(yàn)證行為差異object-is-triple-equals.md 給出了四組極具代表性的示例我們逐一展開(kāi)分析{} {}; // false Object.is({}, {}); // false 1 1; // true Object.is(1, 1); // true 0 -0; // true Object.is(0, -0); // false NaN NaN; // false Object.is(NaN, NaN); // true對(duì)象比較對(duì)象引用語(yǔ)義{} {}為falseObject.is({}, {})同樣為false。原因在于對(duì)象、數(shù)組、函數(shù)等引用類型比較的是引用地址而非結(jié)構(gòu)內(nèi)容——兩個(gè)各自獨(dú)立創(chuàng)建的空對(duì)象指向不同的內(nèi)存位置因此無(wú)論使用哪種比較方式都不相等。若需比較對(duì)象內(nèi)容應(yīng)使用倉(cāng)庫(kù) comparison.yaml 集合中列出的其他方案如對(duì)象屬性匹配、數(shù)組內(nèi)容比較等。普通數(shù)值比較1 1與Object.is(1, 1)均為true。對(duì)于常規(guī)數(shù)字非零、非NaN兩種方式?jīng)]有差別。正零與負(fù)零0 -0為true而Object.is(0, -0)為false。從數(shù)學(xué)語(yǔ)義看0與-0數(shù)值相等遵循這一直覺(jué)但Object.is()會(huì)區(qū)分符號(hào)位將0與-0視為不同值。這一差異在涉及符號(hào)判斷如方向、溫度、坐標(biāo)運(yùn)算結(jié)果的場(chǎng)景中可能產(chǎn)生實(shí)際影響。NaNNaN NaN為false而Object.is(NaN, NaN)為true。這是最反直覺(jué)的一條NaNNot-a-Number是 JavaScript 中唯一一個(gè)不等于自身的值。倉(cāng)庫(kù)中的 value-not-equal-to-itself.md 對(duì)此有專門講解NaN通常來(lái)自無(wú)意義或無(wú)效的數(shù)學(xué)運(yùn)算例如Math.sqrt(-1)或0 / 0因此規(guī)范刻意讓兩個(gè)NaN不相等。NaN與零值理解分歧背后的設(shè)計(jì)意圖NaN為何不等于自身正如 value-not-equal-to-itself.md 所解釋的NaN不是某個(gè)確定的值而是無(wú)法產(chǎn)生正常結(jié)果的哨兵值。兩個(gè)不同的無(wú)效運(yùn)算不應(yīng)被視為相等因此const x Math.sqrt(-1); // NaN const y 0 / 0; // NaN x y; // false x NaN; // false檢測(cè)NaN應(yīng)使用Number.isNaN()它與全局isNaN()的關(guān)鍵區(qū)別在于全局isNaN()會(huì)強(qiáng)制把參數(shù)轉(zhuǎn)換為數(shù)字再判斷因此isNaN(hello)也返回true而Number.isNaN()不做轉(zhuǎn)換只有當(dāng)值本身是NaN時(shí)才返回true因此更穩(wěn)健、更值得優(yōu)先使用。倉(cāng)庫(kù)的 complete-guide-to-js-type-checking.md 也建議在typeof val number的判斷后追加!Number.isNaN(val)來(lái)排除NaN。兩種零值比較算法的語(yǔ)義差異從規(guī)范角度JavaScript 的比較算法可細(xì)分為SameValueObject.is()采用區(qū)分0與-0認(rèn)為兩個(gè)NaN相等Strict Equality采用不區(qū)分0與-0認(rèn)為NaN不等于自身SameValueZeroSet、Map、Array.prototype.includes()等采用不區(qū)分0與-0但認(rèn)為兩個(gè)NaN相等??梢钥吹絆bject.is()更像一個(gè)規(guī)范級(jí)的比較工具它對(duì)NaN與符號(hào)零都給出精確到位的答案。這使其在以下場(chǎng)景格外有用判斷結(jié)果是否為NaNObject.is(x, NaN)可替代Number.isNaN(x)的一部分用途區(qū)分0與-0當(dāng)符號(hào)位有意義時(shí)如表示方向、正負(fù)向位移無(wú)法區(qū)分二者而Object.is()可以實(shí)現(xiàn)精確的緩存/去重鍵比較在需要將NaN視為與自身相等的場(chǎng)景中Object.is()比更符合直覺(jué)。如何選擇Object.is()、還是結(jié)合倉(cāng)庫(kù) object-is-triple-equals.md 與 equality.md 的論述可以形成如下選型原則場(chǎng)景推薦方案原因常規(guī)嚴(yán)格比較類型值語(yǔ)義清晰、性能無(wú)額外開(kāi)銷、可讀性好覆蓋絕大多數(shù)場(chǎng)景需要類型強(qiáng)制轉(zhuǎn)換的比較僅在確定需要隱式轉(zhuǎn)換時(shí)使用且應(yīng)謹(jǐn)慎評(píng)估判斷值是否為NaNNumber.isNaN(val)或Object.is(val, NaN)對(duì)NaN一律返回false無(wú)法直接使用區(qū)分0與-0Object.is()將二者視為相等查找NaN成員數(shù)組/集合Array.prototype.includes()、Set/Map這些 API 內(nèi)部采用 SameValueZero 語(yǔ)義能命中NaN而indexOf基于嚴(yán)格相等無(wú)法命中一個(gè)實(shí)用提示Object.is()在處理NaN時(shí)與Array.prototype.includes()的語(yǔ)義一致后者內(nèi)部也視NaN等于自身因此當(dāng)你需要把NaN當(dāng)作普通值參與相等判斷時(shí)Object.is()是之外更符合直覺(jué)的選擇。在 30-seconds-of-code 中繼續(xù)深入該知識(shí)點(diǎn)屬于倉(cāng)庫(kù) JavaScript 比較系列完整脈絡(luò)可參見(jiàn) comparison.yamljs/comparison集合其中按主題收錄了equality.md與的完整對(duì)比與類型轉(zhuǎn)換示例value-not-equal-to-itself.mdNaN的唯一性與Number.isNaN()/isNaN()的區(qū)別object-is-triple-equals.md本文核心Object.is()與的差異以及對(duì)象比較、數(shù)組比較、日期比較、對(duì)象屬性匹配、數(shù)組內(nèi)容比較等更多相關(guān)片段??偨Y(jié)Object.is()與的差別雖小卻精確地體現(xiàn)在NaN與0/-0這兩類邊界值上Object.is()認(rèn)為NaN等于自身、但認(rèn)為0與-0不等則相反。日常開(kāi)發(fā)中仍應(yīng)以作為默認(rèn)選擇僅在需要精確處理NaN或符號(hào)零時(shí)才引入Object.is()。理解這一差異能幫助你避免諸如NaN NaN意外為 false、正負(fù)零無(wú)法區(qū)分之類的隱蔽 bug寫出行為可預(yù)期的比較邏輯。贊分享教程文檔【免費(fèi)下載鏈接】30-seconds-of-codeCoding articles to level up your development skills項(xiàng)目地址https://gitcode.com/gh_mirrors/30/30-seconds-of-code點(diǎn)擊查看免費(fèi)下載相關(guān)推薦30 Seconds of Interviews 精講JavaScript 中 與 相等運(yùn)算符的本質(zhì)區(qū)別30 Seconds of Interviews 精講JavaScript 中 與 相等運(yùn)算符的本質(zhì)區(qū)別 寬松相等與 嚴(yán)格相教程前端30 seconds of code用 Array.prototype.every() 檢查 JavaScript 數(shù)組中所有值是否相等30 seconds of code用 Array.prototype.every 檢查 JavaScript 數(shù)組中所有值是否相等 判斷數(shù)組中所有元素是否相教程文檔30 seconds of code 實(shí)戰(zhàn)用 JavaScript 生成等差與等比數(shù)列30 seconds of code 實(shí)戰(zhàn)用 JavaScript 生成等差與等比數(shù)列 導(dǎo)讀 本文講解如何在 JavaScript 中僅用幾行 ES6 代碼生教程文檔上一篇如何用 Obsidian Smart Connections 打造智能知識(shí)管理系統(tǒng)2025 完整指南下一篇AISystem 深度學(xué)習(xí)框架中的流水線并行Pipeline Parallelism從 Gpipe 到 PipeDream 原理與 PyTorch 實(shí)現(xiàn)創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考