7

私はルールを知っています:

2 つのオペランドが同じ型でない場合、JavaScript はオペランドを変換してから、厳密な比較を適用します。オペランドのいずれかが数値またはブール値の場合、可能であればオペランドは数値に変換されます。そうでなければ、どちらかのオペランドが文字列の場合、可能であればもう一方のオペランドが文字列に変換されます。

のようなハンドルなので、if("true")合格しますがif("true" == true)失敗します if(NaN == 1)

1つの値がブール値である場合、この背後にある合理的な理由は何なのかと思っていました。PHP のような他の弱い型付け言語では、これは別の方法で処理されます。一方の値がブール値の場合、もう一方の値は比較のためにブール値に変換されます (JavaScript のように両方を数値に変換することはありません)。

この選択は、==オペレーターが慎重に検討して行ったものだと思います。これが選択された機能である理由について、誰かが合理的に提供できますか? これが対処するために選択された一般的なユースケースはありますか? ただの間違いではなかったに違いない。

4

2 に答える 2

8

es-discuss@mozilla.orgメーリングリストのBrendanEichからの非常に迅速な応答:

Perlを考えてみましょう:

$ perl -e 'print 0 == "true";'
1

わかりました。論理的根拠は不十分ですが、1995年5月に、AWK、Perl 4、Python 1.2(IIRC)、TCLの陰でJSを作成しました。

与えられた私はPerlよりもAWKにもっと注意を払うべきだった

$ awk 'END {print(0 == "0")}'
1D
$ awk 'END {print(0 == "")}'
0D

ある意味で、JSの演算子は、NaNに変換することにより、Perl(変換などの非数値文字列)とAWK(変換のみ)==の違いを分割します。そうすれば、少なくとも、"true"0"0"0

js> 0 == ""
true
js> 0 == "true"
false

しかし、完全な真実は、私が他の言語を注意深くエミュレートしていたということではありません。むしろ、PHPのようなサーバー(LiveWire)にJS(当時は「Mocha」)を埋め込むために作業している一部のNetscaperは、ずさんな変換を望んでいたため、プログラマーはHTTPヘッダー文字列(サーバー側)またはHTMLフォームフィールド(クライアント側)を、たとえば、 404など。プログラマーによる明示的な強制はありません。

しかし、それは90年代でした、私は涙を流して急いでいました、これらの元ボーランドNetscapersは永続的でした。それで、去年のストレンジループで言ったように、「私はばかだった!彼らが望むものを彼らに与えた!」

暗黙の変換は、JSの急いで設計された私の最大の後悔です。'with'を含めても!

==演算子を使用したブール値と比較して、ブール値に変換しないという選択が行われた正確な理由を知っている人はいますか?

一般的な考え方は、狭いタイプは広くする必要があるということです。したがって、C ++の場合と同様に、ブール値をにtrue == 1投影します。{false, true}{0, 1}

trueしかし、あなたの例の他のオペランドはであるため、文字列に広げてみません"true"か?良い質問。オペランドが数値またはブール値である場合に文字列を数値として比較する傾向は、HTTPヘッダーと数値文字列のHTMLフォームフィールドの使用例に起因します。繰り返しになりますが、これは正当な理由ではありませんが、JSが「機能する」方法です:-|。

これは、ECMA-262 Edition 5.1仕様、11.9.3抽象等式比較アルゴリズム、ステップ6および7(ステップ4および5に照らして読む)で確認できます。

4. Type(x)がNumberで、Type(y)がStringの場合、比較の結果x == ToNumber(y)を返します。
5. Type(x)がStringで、Type(y)がNumberの場合、比較の結果ToNumber(x)==yを返します。
6. Type(x)がブール値の場合、比較ToNumber(x)==yの結果を返します。
7. Type(y)がブール値の場合、比較の結果x == ToNumber(y)を返します。

Type(x)これはすべて、とType(y)forx == yが同じではない大きな「else節」に含まれています。

申し訳ありませんが、ここには知恵の真珠(原文のまま)はありません。暗黙的な変換に加えて、データを失うことなく他のオペランドを保持できる最も狭い幅にオペランドを直接(中間変換なしで)広げない==でください。!=この数への狭められた文字列は単なる失敗です。

このボッチを修正した場合でも、次のようになります。

0 == "0"
1 == "1"
true != "1"
false != "0"

しかし、あなたの例が望むものもあります:

true == "true"
false != ""

文字列変換よりも数値の優先順位をボッチと呼んでいると、文字列から数値に狭まるため、true == "1"またははありません。false == "0"確かに、ナローイングはビットを失うことはなく、に戻って拡大することもできますが、0==の暗黙の変換仕様から文字列に対するすべてのバイアスを削除するとどうなるかを説明するつもりでした。"0"1"1"

そのような変更は、Web上の多くのコードを壊しますか?私はそれがそうするであろう多額を賭けるでしょう。

一部の人は、内部での暗黙の変換に加えて、このボッチを、常に(変換しないため)使用===!==、完全に回避する別の理由としてとらえ==てい!=ます。他の人は同意しません(特にテストするときx == null、1人のオペレーターによる方法test x === null || x === undefined)。

==Webはほとんど互換性を持って成長するので、非常に古いフォームがなくなるまで、私たちはandに固執します。!=したがって、ずさんな等式演算子が何をするかを学ぶことは有益だと思います。そうすれば、私には、それらが勝つ場所でそれらを使用できるように思われます。

typeof x == "function"、など。
x == null

それ以外の場合は、とを使用===!==ます。

オペランドが数値またはブール値である場合に文字列を数値として比較する傾向は、HTTPヘッダーと数値文字列のHTMLフォームフィールドの使用例に起因します。繰り返しになりますが、これは正当な理由ではありませんが、JSが「機能する」方法です:-|。

もう1つの注意:文字列から数値への絞り込みは、数値以外、空でない文字列から数値への暗黙の変換の試みが例外。

ここに、JSの設計ビットにおける別のパス依存バイアスがあります。ES3までJS1またはECMA-262標準での試行/キャッチはありません。

例外処理がないということは、そのようなプロパティがない場所でプロパティgetがundefined欠落していることも意味します。それはまだ噛み付いています、おそらく暗黙の変換が噛むのと同じかそれ以上です。これは、Web JSの受賞歴のある「オブジェクト検出」パターンの基礎でもあり、これまでに見た他のすべてのバージョン管理スキーム、特に明示的な番号付けとオプトインに基づく事前のスキームをかなり上回っています。obj.fooobj==

時間をかけてオブジェクト検出用の実存演算子を追加すれば、次のように書くことができます。

function emulateRequestAnimationFrame(...) {...}
if (!window.requestAnimationFrame?)
  window.requestAnimationFrame = emulateRequestAnimationFrame;

IOW、私がwindow.noSuchProperty投げただけで真実であるwindow.noSuchProperty?と評価した場合、またはfalse(詳細はまだ未定です。「フェイルファストオブジェクト破壊」スレッドの復活、Nilのアイデアを参照してください)。

于 2013-01-06T23:10:24.560 に答える
3

いくつかの説明が必要だと思います。ECMA 仕様によると、if ステートメントの式全体(括弧内の部分) がブール値に変換されます。

したがって、次のように想像してください。

if (ToBoolean("true" == true)) {  //false

if (ToBoolean("true")) { //true

ToBoolean 強制が if 式に追加された理由は、式が常に安全かつ正しく評価されるようにするためだったと思います。

ToBoolean は、単一の値をブール値に強制します。比較では、各値をブール値に強制することはありません。かなり奇妙な結果が得られるため、意味がありません。同等性をチェックする、別の操作です。もう一方の値がブール値に変換されない理由についてはよくわかりませんが、Mozilla ECMA メーリング リストを試してみてください: https://mail.mozilla.org/listinfo/es-discuss

見る:

http://www.ecma-international.org/ecma-262/5.1/#sec-9.2

http://www.ecma-international.org/ecma-262/5.1/#sec-12.5

http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.1

http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3

http://www.ecma-international.org/ecma-262/5.1/#sec-8.7.1

于 2013-01-06T17:20:23.303 に答える