30

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);

undefined に対するチェックのようには見えません。オブジェクトに対して使用する場合と同じ (1:1) 動作を実現する唯一の方法は、より大きなチェックを使用することでした。

console.log test.test if typeof test.test != "undefined" and test.test != null

問題は - 私は何か間違ったことをしていますか? または、コンパイルされたコードは、プロパティの存在を確認するのに十分なものですか (型変換による null チェック)?

4

3 に答える 3

54

これは、実存的な演算子との一般的な混乱のポイントです。

x?

にコンパイルします

typeof test !== "undefined" && test !== null

そして他の時にはそれはただコンパイルします

x != null

はまたはのいずれかでx != nullあるためfalseこの2つは同等です。を表現するよりコンパクトな方法です。コンパイルが行われる理由は、コンパイラーがまったく定義されていないと見なすためです。その場合、等価性テストを実行するとがトリガーされます。xnullundefinedx != null(x !== undefined && x !== null)typeofxReferenceError: x is not defined

特定のケースでtest.testは、に値undefinedがある場合がありますが、既存のオブジェクトの未定義のプロパティを参照してを取得することはできないReferenceErrorため、コンパイラはより短い出力を選択します。

于 2012-04-03T14:32:42.793 に答える
20

この JavaScript:

a.foo != null

fooのプロパティaがどちらundefinedでもないかどうかを実際にチェックしますnull。は ではなくa.foo?を使用する JavaScript に変換されることに注意してください。行う変換は、これらの両方が真であることを意味します。!= null!== null!=

null == null
undefined == null

プレーンは次のa?JavaScript になります。

typeof a !== "undefined" && a !== null

確認する条件が 3 つあります。

  1. aどこかにスコープがありますか?
  2. aの値を持っていますundefinedか?
  3. aの値を持っていますnullか?

最初の条件は重要です。スコープ内にa != nullない場合は ReferenceError をトリガーしますが、そうしないと言うだけです。チェックは2の条件も処理します。次に、不要なパフォーマンスのペナルティなしで3を処理するため、厳密なテストで終了できます(注: andは暗黙的な変換によりandよりも遅くなります)。atypeof a === 'undefined'typeofa === undefineda !== null!=!===!=====

!=whatとdoについて少し読むと、!==実り多いかもしれません。

MDN: 比較演算子


削除された回答に関するコメントに関する限り、ステートメントを完了すると、完全if(a.foo)に有効な構文になります。if

if(a.foo)
    do_interesting_things()
# or
do_interesting_things() if(a.foo)

ただし、if(a.foo)とは、 、、および のif(a.foo?)処理方法が異なります。0false''

于 2013-11-15T21:02:25.137 に答える
4

当てずっぽう; 試しましたconsole.log test.test if test?.test?か?

でテストしたところcoffee -p -e 'console.log test.test if test?.test?'、次のようにコンパイルされます。

(関数() {

if ((typeof test !== "未定義" && test !== null ? test.test : void 0) != null) { console.log(test.test); }

}).call(これ);

于 2012-04-03T10:40:10.983 に答える