あまり知られていない JS の問題: [] == ![] は true ですが、{} == !{} は false です

あまり知られていない JS の問題: [] == ![] は true ですが、{} == !{} は false です
console.log( [] == ![] ) // 真
console.log( {} == !{} ) // 偽

文字列、数値、ブール値の等価性を比較する場合、問題は比較的単純です。しかし、オブジェクトを比較するとなると、問題は複雑になります。 ECMAScript の元の等価演算子と不等価演算子は、比較を実行する前にオブジェクトを類似の型に変換しました。後になって、この変換が合理的であったかどうかを疑問視する人もいました。最後に、ECMAScript のソリューションは、次の 2 つの演算子セットを提供することです。

等価と不等価 - まず変換してから比較します (==)
合同と不同 - 変換せずに比較する (===)

ECMAScript の等価演算子は、2 つの等号 (==) で表されます。2 つのオペランドが等しい場合は、true を返します。この演算子は、最初にオペランドを変換し (通常は強制変換と呼ばれます)、次にそれらの等価性を比較します。

異なるデータ型を変換する場合、等価演算子と不等価演算子については、次の基本的な変換ルールがJS Elevationという本に記載されています。

① 一方のオペランドがブール値の場合、等価性を比較する前に数値に変換されます。つまり、false は 0 に変換され、true は 1 に変換されます。

② 一方のオペランドが文字列で、もう一方のオペランドが数値の場合、等しいかどうか比較する前に文字列を数値に変換します。

③. 一方のオペランドがオブジェクトでもう一方がそうでない場合は、オブジェクトの valueOf() メソッドを呼び出し、取得したプリミティブ型の値を使用して、前の規則に従って比較します。

これら 2 つの演算子は、比較を実行するときに次の規則に従います。

①、nullとundefinedは等しい

② 等価性を比較する前に、nullとundefinedを他の値に変換することはできません

③. 一方のオペランドが NaN の場合、等価演算子は false を返し、不等価演算子は true を返します。重要: 両方のオペランドが NaN の場合でも、規則により NaN は NaN と等しくないため、等価演算子は false を返します。

④. 両方のオペランドがオブジェクトの場合、それらが同じオブジェクトであるかどうかを比較します。両方のオペランドが同じオブジェクトを指している場合、等価演算子はtrueを返します。そうでない場合はfalseを返します。

ここで余談ですが、[] と {} はどちらも参照型であり、ヒープ メモリに格納され、スタック メモリには、このヒープ メモリに対応するデータを指す 1 つ以上のアドレスが存在します。したがって、参照型データに対して == 演算子を使用する場合、比較されるのは実際の値ではなくアドレスです。

ここで、[] == ! [] の結果がなぜ真なのかを議論しましょう。

①. オペレータの優先度に応じて、! の優先度は == よりも高いので、最初に実行されます![]

!変数はブール型に変換できます。null、undefined、NaN、空文字列 ('') の否定は true になり、それ以外は false になります。

つまり、[]演算後の結果は偽です

つまり、[] == ! [] は [] == false と同等です。

② 上記のルール(オペランドの1つがブール値の場合、等価性を比較する前に数値に変換されます。falseは0に変換され、trueは1に変換されます)に従って、falseを0に変換する必要があります。

つまり、[] == ! [] は [] == false と同等であり、これは [] == 0 と同等です。

③. 上記のルールに従って(一方のオペランドがオブジェクトで、もう一方のオペランドがオブジェクトでない場合は、オブジェクトの valueOf() メソッドが呼び出され、取得したプリミティブ型の値が前のルールに従って比較されます。オブジェクトに valueOf() メソッドがない場合は、toString() が呼び出されます)

空の配列の場合、[].toString() -> '' (空の文字列を返します)

つまり、[] == 0 は '' == 0 と同等である。

④ 上記の規則に従って(一方のオペランドが文字列で、もう一方のオペランドが数値の場合、等価性を比較する前に文字列を数値に変換します)

Number('') -> 0 を返します

これは 0 == 0 と同等であり、当然 true を返します。

要約すると:

[] == ! [] -> [] == 偽 -> [] == 0 -> '' == 0 -> 0 == 0 -> 真

{} == !{} の場合も同様です。

キーは {}.toString() -> NaN (NaN を返します)

上記の規則によれば(1つのオペランドがNaNの場合、等価演算子はfalseを返します)

要約すると:

{} == ! {} -> {} == 偽 -> {} == 0 -> NaN == 0 -> 偽

すると、次の 2 つの質問には誰でも簡単に答えられると思います。

console.log( [] == !{} ) // 真
console.log( {} == ![] ) // false

要約する

これで、[] == ![] は true と評価されるのに、{} == !{} は false と評価されるという、あまり知られていない JS の問題に関するこの記事は終了です。JS [] == ![] が true と評価されることの詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援してください。

<<:  mysql5.7.22 ダウンロードプロセス図

>>:  Linux サーバーでフォルダー、ファイル、解凍コマンドを削除する方法

推薦する

Linux 上の MariaDB は root ユーザーで起動します (推奨)

最近、セキュリティ製品をテストする必要があったため、mariadb の起動ユーザーを root に調...

Nginx proxy_redirect の使用方法の詳細な説明

今日、Apache の nginx リバース プロキシを実行していたときに、ちょっとした問題に遭遇し...

MySQL マスタースレーブレプリケーションのいくつかのレプリケーション方法の概要

非同期レプリケーションMySQL レプリケーションは、デフォルトでは非同期です。マスター スレーブ ...

複数の .sql ファイルを MySQL に効率的にインポートする方法の詳細な説明

MySQL には、複数の .sql ファイル (SQL ステートメントを含む) をインポートする方法...

Jupyter Notebook で JavaScript を実行する方法

その後、VSC で Jupyter Notebook を使用する方法も追加しました...アナコンダを...

Vue+elementUI コンポーネントは、折りたたみ可能な動的レンダリングのマルチレベル サイドバー ナビゲーションを再帰的に実装します。

かなり前に実装された機能ですが、クリックすると選択したメニュー項目の背景色が白くなることに気付きまし...

Vueは2つのルーティング許可制御メソッドを実装しています

目次方法 1: ルーティング メタ情報 (meta)方法 2: ルーティング テーブルを動的に生成す...

Vue3 カプセル化された虫眼鏡コンポーネントのサンプルコード

目次コンポーネントインフラストラクチャ目的: 画像拡大鏡機能を実現するvueuseをインストールする...

Vue.$set の失敗の落とし穴の発見と解決

偶然、プロジェクト内でVue.$setが無効であることがわかりましたデータ フィルタリングを追加する...

Linux システム修復モード (シングル ユーザー モード)

目次序文1. シングルユーザーモードでの一般的なバグ修正2. シングルユーザーモードでシステムパスワ...

Typora コードブロックのカラーマッチングとタイトルシリアル番号実装コード

効果: タイトルには独自のシリアル番号があり、コードブロックには配色があり、コードブロックの左上隅に...

MySQLの行数カウントに関する簡単な説明

各テーブルの行数をカウントするために使用される MySQL count() 関数は、誰もがよく知って...

202 無料の高品質 XHTML テンプレート (1)

ここで 123WORDPRESS.COM はこれらのテンプレートの最初の部分を紹介します。各テンプレ...

el-table カプセル化に基づくドラッグ可能な行と列、および選択列コンポーネントの実装

効果環境が必要ビュー要素UIドラッグアンドドロッププラグインSortable.js必要な構成プロパテ...

WiFi 開発 | WiFi ワイヤレス テクノロジーの紹介

目次WiFiワイヤレステクノロジーの紹介1. WiFiテクノロジーの概要2. ESP8266の紹介W...