CoffeeScriptの実存演算子を使用して、いくつかのオブジェクトプロパティの未定義をチェックしたいと思います。しかし、私は少し問題に遭遇しました。
このようなコード:
console.log test if test?
コンパイル先:
if (typeof test !== "undefined" && test !== null) console.log(test);
これが私が見たい行動です。ただし、次のようにオブジェクトプロパティに対して使用しようとすると、次のようになります。
console.log test.test if test.test?
私はそのようなものを手に入れます:
if (test.test != null) console.log(test.test);
これは、未定義に対するチェックのようには見えません。オブジェクトに使用するのと同じ(1:1)動作を実現できる唯一の方法は、より大きなチェックを使用することでした。
console.log test.test if typeof test.test != "undefined" and test.test != null
問題は、私は何か間違ったことをしているのかということです。または、コンパイルされたコードは、プロパティの存在をチェックするのに十分ですか(型変換を使用したnullチェック)?
これは、実存演算子との一般的な混乱点です。
x?
にコンパイルされます
typeof test !== "undefined" && test !== null
そして他の時にはそれはただコンパイルします
x != null
2つは同等ですfalse
がx
またはnull
の場合、x != null
はundefined
になるためです。したがって、x != null
は、(x !== undefined && x !== null)
をよりコンパクトに表現する方法です。 typeof
コンパイルが発生する理由は、コンパイラがx
がまったく定義されていない可能性があると判断するためです。この場合、等価性テストを実行するとReferenceError: x is not defined
がトリガーされます。
特定のケースでは、test.test
の値はundefined
ですが、既存のオブジェクトの未定義のプロパティを参照してReferenceError
を取得することはできないため、コンパイラは短い出力を選択します。
このJavaScript:
a.foo != null
実際には、foo
のa
プロパティがundefined
でもnull
でもないかどうかをチェックします。 a.foo?
は、!= null
ではなく!== null
を使用するJavaScriptに変換されることに注意してください。 !=
が行う変換は、これらの両方が真であることを意味します。
null == null
undefined == null
プレーンなa?
は次のJavaScriptになります。
typeof a !== "undefined" && a !== null
チェックする条件が3つあるためです。
a
はどこかにありますか?a
の値はundefined
ですか?a
の値はnull
ですか?最初の条件は重要です。スコープにa
がない場合、a != null
はReferenceErrorをトリガーしますが、typeof a === 'undefined'
はトリガーしません。 typeof
チェックは、2のa === undefined
条件も処理します。次に、厳密なa !== null
テストで終了できます。これは、不要な!=
のパフォーマンスペナルティなしで3を処理するためです(注:!=
と==
は暗黙の変換のため、!==
および===
よりも遅くなります)。
!=
と!==
が何をするかについて少し読むと、実り多いかもしれません。
削除された回答に対するコメントに関する限り、if(a.foo)
は完全に有効な構文ですifif
ステートメント:
if(a.foo)
do_interesting_things()
# or
do_interesting_things() if(a.foo)
ただし、if(a.foo)
とif(a.foo?)
は、0
、false
、および''
の処理方法が異なります。
当てずっぽう; console.log test.test if test?.test?
を試しましたか?
coffee -p -e 'console.log test.test if test?.test?'
でテストしたところ、次のようにコンパイルされます。
(関数() {
if((typeof test!== "undefined" && test!== null?test.test:void 0)!= null){console.log(test.test); }
})。call(this);