JavaScriptの抽象的な等値比較
13122 ワード
JavaScriptの抽象等式比較演算子は、いわゆる型強制平等チェックです.必要に応じてタイプを強制し、いくつかのかなり奇妙な結果につながることができます.
しかし、私たちはこのすべての意味をなすことができます.
背後にアルゴリズムがある
あなたが= =演算子を使用するたびに、実際には比較の結果を決定するアルゴリズムがあります.
このアルゴリズムは、ECMA仕様(JavaScriptの後ろのspec)内にその場所を持ち、7.7.15で見つけることができます.
それは実際にはかなり長いですし、多くのスペースがかかりますが、すべての可能な入力をカバーし、任意の比較の出力を決定する簡潔な方法を提供します.あなたはそれをよりよく読むことができるように私は少し処理した以下から抜粋を見ることができます.
アルゴリズム を返します. を返します. If If If If If リターン を返します. を返します. を返します. if リターン リターン を返します. If リターン if リターン リターン を返します. If リターン リターン If リターン リターン If If を返します. を返します. を返します. セット If 比較結果を返す を返します. を返します. を返します. を返します. を返します. を返します. If の値 リターン リターン リターン このすべては少し威圧的に思えるかもしれませんが、それは大丈夫です.あなたはそれが理解できるように十分なロジックがあることがわかります.しかし、我々が入る前に、あなたは最初にこのアルゴリズムの中で参照されるいくつかの機能について学ばなければなりません.
サポート機能
種類( x )
これはtypeof演算子ではなく、値を入力した値を正確に返すランタイム関数です.
type ( null )は実際にはNULLで、例えばオブジェクトではありません.
ナトリウム
これもランタイム機能です.これは基本的に番号(x)を呼び出すと同じ動作します.
StringToBigint
これは基本的に私たちが今カバーしないいくつかの追加とtonumberです.
トゥプリミティブ
これは任意の複雑なオブジェクトをプリミティブに変換するランタイム機能です.もう一度アルゴリズム全体があり、次のようになります. type ( input )がオブジェクトの場合、 If もし その他 セット セット If セット を返します. スローする If If セット その他 セット ごとに If セット を返します. スローする リターン
例を用いてそれを理解する
今では'アルゴリズムの多く'を手にしているが、まだその知識を実際に適用することは非常に困難かもしれません.これは例が入っているところです.彼らは通常より複雑なことを理解するのに大いに役立つ.
例1
始めましょう
例2
例を続けましょう
例3
一歩一歩進んで、我々の比較で1つのオブジェクトを使いましょう
例4
試しましょう
次は何ですか.
現在、あなた自身の例を考え出すことができます.単にアルゴリズムに従ってください、あなたは間違いなく毎回正しい答えを得るでしょう.しかし、あなたはもちろん、あなたのブラウザーのdevツールで式を単にログで記録して、あなたのブラウザが言うものに対してあなたの結果を比較することによって正しいことを確実にすることができます.
もう少し練習すると、確かに常にいくつかのJavaScriptクイズに将来的に答えを知っているよ!
去る前に
あなたが私の内容が好きならば、私を訪ねてください、そして、おそらく、あなたはあなたが見るものが好きでしょう.
しかし、私たちはこのすべての意味をなすことができます.
背後にアルゴリズムがある
あなたが= =演算子を使用するたびに、実際には比較の結果を決定するアルゴリズムがあります.
このアルゴリズムは、ECMA仕様(JavaScriptの後ろのspec)内にその場所を持ち、7.7.15で見つけることができます.
それは実際にはかなり長いですし、多くのスペースがかかりますが、すべての可能な入力をカバーし、任意の比較の出力を決定する簡潔な方法を提供します.あなたはそれをよりよく読むことができるように私は少し処理した以下から抜粋を見ることができます.
アルゴリズム
x
) と同じです(y
), thenx
) は、x
is NaN
, リターンfalse
. y
is NaN
, リターンfalse
. x
と同じ値y
, リターンtrue
. x
is +0
and y
is -0
, リターンtrue
. x
is -0
and y
is +0
, リターンtrue
. false
. x
) が定義されていない場合、true
. x
) がNULLtrue
. x
) は文字列x
and y
と同じ文字列(同じ長さ、シーケンス内の同じ文字)、そしてtrue
. false
. x
) はx
is true
and y
is true
, thentrue
. x
is false
and y
is false
, thentrue
. false
. x
) はシンボルで、x
and y
は両方とも同じシンボル値、true
. false
. x
and y
は、true
. false
. x
is null
and y
is undefined
, リターンtrue
. x
is undefined
and y
is null
, リターンtrue
. x
) と数値y
) は文字列で、x == tonumber ( y )の結果を返します.x
) 文字列と型y
) が指定されている場合、比較関係のtonx ( x )== yの結果を返します.x
) はbigint型とtype (y
) は文字列n
を返します.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で、x
or y
どれかNaN
, +INFINITY
, or -INFINITY
, リターンfalse
. x
の値はy
, thentrue
. false
. false
. サポート機能
種類( x )
これはtypeof演算子ではなく、値を入力した値を正確に返すランタイム関数です.
type ( null )は実際にはNULLで、例えばオブジェクトではありません.
ナトリウム
これもランタイム機能です.これは基本的に番号(x)を呼び出すと同じ動作します.
StringToBigint
これは基本的に私たちが今カバーしないいくつかの追加とtonumberです.
トゥプリミティブ
これは任意の複雑なオブジェクトをプリミティブに変換するランタイム機能です.もう一度アルゴリズム全体があり、次のようになります.
preferredType
が存在しないhint
to "default"
preferredType
ヒント文字列hint
to "string"
hint
to "number"
exoticToPrim
to input[Symbol.iterator]
exoticToPrim
がundefined
, thenresult
to exoticToPrim(hint)
result
) オブジェクトでないresult
TypeError
例外hint
is "default"
, セットhint
to "number"
hint
is "string"
, then methodNames
to ["toString", "valueOf"]
methodNames
to ["valueOf", "toString"]
name
インリストmethodNames
, 順序で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クイズに将来的に答えを知っているよ!
去る前に
あなたが私の内容が好きならば、私を訪ねてください、そして、おそらく、あなたはあなたが見るものが好きでしょう.
Reference
この問題について(JavaScriptの抽象的な等値比較), 我々は、より多くの情報をここで見つけました https://dev.to/oliverjumpertz/how-the-abstract-equality-comparison-in-javascript-works-80iテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol