JavaScriptの抽象的な等値比較


JavaScriptの抽象等式比較演算子は、いわゆる型強制平等チェックです.必要に応じてタイプを強制し、いくつかのかなり奇妙な結果につながることができます.
しかし、私たちはこのすべての意味をなすことができます.

背後にアルゴリズムがある
あなたが= =演算子を使用するたびに、実際には比較の結果を決定するアルゴリズムがあります.
このアルゴリズムは、ECMA仕様(JavaScriptの後ろのspec)内にその場所を持ち、7.7.15で見つけることができます.
それは実際にはかなり長いですし、多くのスペースがかかりますが、すべての可能な入力をカバーし、任意の比較の出力を決定する簡潔な方法を提供します.あなたはそれをよりよく読むことができるように私は少し処理した以下から抜粋を見ることができます.

アルゴリズム
  • を返します.x ) と同じです(y ), then
  • を返します.x ) は、
  • If x is NaN , リターンfalse .
  • If y is NaN , リターンfalse .
  • If x と同じ値y , リターンtrue .
  • If x is +0 and y is -0 , リターンtrue .
  • If x is -0 and y is +0 , リターンtrue .
  • リターンfalse .
  • を返します.x ) が定義されていない場合、true .
  • を返します.x ) がNULLtrue .
  • を返します.x ) は文字列
  • if x and y と同じ文字列(同じ長さ、シーケンス内の同じ文字)、そして
  • リターンtrue .
  • リターンfalse .
  • を返します.x ) は
  • If x is true and y is true , then
  • リターンtrue .
  • if x is false and y is false , then
  • リターンtrue .
  • リターンfalse .
  • を返します.x ) はシンボルで、
  • If x and y は両方とも同じシンボル値、
  • リターンtrue .
  • リターンfalse .
  • If x and y は、
  • リターンtrue .
  • リターンfalse .
  • If x is null and y is undefined , リターンtrue .
  • If x is undefined and y is null , リターンtrue .
  • を返します.x ) と数値y ) は文字列で、x == tonumber ( y )の結果を返します.
  • を返します.x ) 文字列と型y ) が指定されている場合、比較関係のtonx ( x )== yの結果を返します.
  • を返します.x ) はbigint型とtype (y ) は文字列
  • セットn を返します.
  • If n is NaN , falseを返します.
  • 比較結果を返すx == n.
  • を返します.x ) 文字列と型y ) がbigintの場合、比較結果を返すy == x .
  • を返します.x ) がbooleanの場合、比較tonumber ( x )== yの結果を返します.
  • を返します.y ) がbooleanの場合、x == tonumber ( y )の結果を返す.
  • を返します.x ) 文字列、数値、bigint、シンボルと型y ) is objectはx == topriror ( y )の比較結果を返します.
  • を返します.x ) オブジェクトと型y ) は文字列、数値、bigint、またはシンボルのいずれかであり、比較結果の原始値( x )== yを返す.
  • を返します.x ) はbigint型とtype (y ) が指定された場合、x ) と数値y ) はbigintで、
  • If x or y どれかNaN , +INFINITY , or -INFINITY , リターンfalse .
  • の値x の値はy , then
  • リターンtrue .
  • リターンfalse .
  • リターンfalse .
  • このすべては少し威圧的に思えるかもしれませんが、それは大丈夫です.あなたはそれが理解できるように十分なロジックがあることがわかります.しかし、我々が入る前に、あなたは最初にこのアルゴリズムの中で参照されるいくつかの機能について学ばなければなりません.

    サポート機能

    種類( x )
    これはtypeof演算子ではなく、値を入力した値を正確に返すランタイム関数です.
    type ( null )は実際にはNULLで、例えばオブジェクトではありません.

    ナトリウム
    これもランタイム機能です.これは基本的に番号(x)を呼び出すと同じ動作します.

    StringToBigint
    これは基本的に私たちが今カバーしないいくつかの追加とtonumberです.

    トゥプリミティブ
    これは任意の複雑なオブジェクトをプリミティブに変換するランタイム機能です.もう一度アルゴリズム全体があり、次のようになります.
  • type ( input )がオブジェクトの場合、
  • If preferredType が存在しないhint to "default"
  • もしpreferredType ヒント文字列hint to "string"
  • その他
  • セットhint to "number"
  • セットexoticToPrim to input[Symbol.iterator]
  • If exoticToPrimundefined , then
  • セットresult to exoticToPrim(hint)
  • を返します.result ) オブジェクトでないresult
  • スローするTypeError 例外
  • If hint is "default" , セットhint to "number"
  • If hint is "string" , then
  • セットmethodNames to ["toString", "valueOf"]
  • その他
  • セットmethodNames to ["valueOf", "toString"]
  • ごとにname インリストmethodNames , 順序で
  • If input[name] が存在する(未定義)
  • セットresult to input[name]()
  • を返します.result ) オブジェクトでないresult
  • スローするTypeError 例外
  • リターンinput

  • 例を用いてそれを理解する
    今では'アルゴリズムの多く'を手にしているが、まだその知識を実際に適用することは非常に困難かもしれません.これは例が入っているところです.彼らは通常より複雑なことを理解するのに大いに役立つ.

    例1
    始めましょう1 == "1" 光のエントリとして.
    1 == "1";
    // =>
    // Step 4 applies, x is Number and y is string.
    // So it is evaluated as
    1 == Number("1");
    // Number("1") yields 1, so we're at
    1 == 1;
    // which is
    true;
    

    例2
    例を続けましょうtrue == 0 .
    true == 0;
    // =>
    // Step 9 applies, as x is a boolean.
    // It is evaluated as
    Number(true) == 0;
    // Number(true) yields 1, so we're at
    1 == 0;
    // which is
    false;
    

    例3
    一歩一歩進んで、我々の比較で1つのオブジェクトを使いましょう"" == [] .
    "" == [];
    // =>
    // Step 10 applies, as x is a string and y is an object.
    // [] needs to be converted into a primitive.
    // [][Symbol.toPrimitive] is undefined so that doesn't help.
    // The type hint is "default", and thus "number" is passed, according to the primitive
    // conversion algorithm
    // The methods now used are [valueOf, toString].
    // [].valueOf() returns [] again, so once again no help.
    // [].toString() yields "" which is a primitive, so the algorithm terminates successfully.
    "" == "";
    // according to step 1.4.1 yields
    true;
    

    例4
    試しましょう[] == ![] さあ.それは通常、人々が少なくとも眉を上げるようになる奇妙な比較の1つです.
    [] == ![];
    // ![] is evaluated first and is no actual part of the comparison.
    // ![] is a boolean conversion together with negation, so you could also
    // read it as
    [] == !Boolean([]);
    // Boolean([]) yields true, as all objects do
    [] == !true;
    // and that negated is of course
    [] == false;
    
    // Now step 9 of the algorithm applies, as y is a boolean
    [] == Number(false);
    // Number(false) yields 0
    [] == 0;
    // And the algorithm calls itself again where this time, step 11 applies, as x is an object and y is a number
    
    ToPrimitive([]) == 0;
    // [][Symbol.toPrimitive] is undefined so that doesn't help.
    // The type hint is still at "default" so it gets replaced with "number" according to step 1.6 of the primitive conversion algorithm.
    // The methods used are now [valueOf, toString].
    // [].valueOf() yields [] again which doesn't help.
    // [].toString() however results in "", an empty string.
    
    "" == 0;
    // The algorithm is once again calling itself where this time step 5 applies, as
    // x is a string and y is a number.
    
    Number("") == 0;
    // Number("") results in 0 and the algorithm calls itself once again.
    
    0 == 0;
    // This time step 1.1.3 applies, as both values have type number.
    // Because both sides have the exact same value, the result can only be.
    true;
    

    次は何ですか.
    現在、あなた自身の例を考え出すことができます.単にアルゴリズムに従ってください、あなたは間違いなく毎回正しい答えを得るでしょう.しかし、あなたはもちろん、あなたのブラウザーのdevツールで式を単にログで記録して、あなたのブラウザが言うものに対してあなたの結果を比較することによって正しいことを確実にすることができます.
    もう少し練習すると、確かに常にいくつかのJavaScriptクイズに将来的に答えを知っているよ!

    去る前に
    あなたが私の内容が好きならば、私を訪ねてください、そして、おそらく、あなたはあなたが見るものが好きでしょう.