55

以下は、理論上の JavaScript に関する質問です。以下が単一のステートメントに変換できるかどうか興味があります。

if(!window.foo){
  window.foo = [];
}
window.foo.push('bar');

おそらく誰もがこのコードを以前に書いたことがあるでしょうが、1 行で実行できるでしょうか?
最初は、次のようなものがうまくいくと思いました:

(window.foo || window.foo = []).push('bar');

しかし、割り当てが無効なため、それは機能しません。次に、プッシュで何かをチェーンしようとしましたが、プッシュが配列を返さないため、うまくいきません。

これがプレーンな JavaScript で実行できるかどうかについて何か考えはありますか?
(ちなみに結果はそのはずですwindow.foo = ['bar']

4

4 に答える 4

92

割り当てが逆になっています*。そのはず:

(window.foo = window.foo || []).push('bar');

JavaScriptの||演算子は、ブール値を返しません。左側が正しければ左側を返し、そうでない場合は右側を返します。

a = a || [];

と同等です

a = a ? a : [];

したがって、上記を記述する別の方法は次のとおりです。

(window.foo = window.foo ? window.foo : []).push('bar');

*詳細についてはコメントを参照してください

于 2013-01-30T21:30:22.877 に答える
15

意図したとおりに動作するように括弧を追加すると、コードは正常に機能します。

(window.foo || (window.foo = [])).push('bar');

括弧がないと、window.foo || window.foo最初に評価してから配列をその結果に割り当てる必要があると考えられますが、これは不可能です。

于 2013-01-30T21:36:34.160 に答える
13

この質問により、楽しみのためにさまざまなオプションを試すことができました。元の配列参照の代わりに長さを返すのは残念pushですが、さらに短い式の場合は、すぐに反復したり、マップしたりできるものがあると便利です。

window.foo = (window.foo||[]).concat(['bar']); // always returns array, allowing:
(window.foo = (window.foo||[]).concat(['bar'])).forEach( ... )

(window.foo = window.foo||[]).push('bar'); // always returns length

window.foo && window.foo.push('bar') || (window.foo = ['bar']); // playing around
于 2013-01-30T21:30:29.570 に答える
4

2021 アップデート

@zzzzBovの役立つ回答

(window.foo = window.foo || []).push('bar');

||=new演算子、論理 OR 代入1を使用してさらに簡略化できます。

(window.foo ||= []).push('bar');

1 tcs39/proposal-logical-assignmentを参照してください。現在はステージ4 で、主要なブラウザーでサポートされています

于 2021-11-08T14:44:08.573 に答える