web-dev-qa-db-ja.com

CoffeeScriptの実存演算子を使用して、いくつかのオブジェクトプロパティの未定義を確認するにはどうすればよいですか?

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チェック)?

26
Przemek

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

x?

にコンパイルされます

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

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

x != null

2つは同等ですfalsexまたはnullの場合、x != nullundefinedになるためです。したがって、x != nullは、(x !== undefined && x !== null)をよりコンパクトに表現する方法です。 typeofコンパイルが発生する理由は、コンパイラがxがまったく定義されていない可能性があると判断するためです。この場合、等価性テストを実行するとReferenceError: x is not definedがトリガーされます。

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

51
Trevor Burnham

このJavaScript:

a.foo != null

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

null == null
undefined == null

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

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

チェックする条件が3つあるためです。

  1. スコープ内にaはどこかにありますか?
  2. aの値はundefinedですか?
  3. aの値はnullですか?

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

!=!==が何をするかについて少し読むと、実り多いかもしれません。

MDN:比較演算子


削除された回答に対するコメントに関する限り、if(a.foo)は完全に有効な構文ですififステートメント:

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

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

20
mu is too short

当てずっぽう; 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);

4
Marius Kjeldahl