10

さまざまな言語の三項演算子について読んでいて、Javascript セクションで興味深いことに気付きました。 http://en.wikipedia.org/wiki/%3F:#JavaScript

JavaScript の条件演算子は、他の BCPL 派生バリアントと同じ構文と優先順位の構造を持っていますが、セマンティクスに大きな違いがあり、左辺を返します。

最初の文は、javascript での 3 項の戻り値が左辺値であることを示しているため、いくつかの例を試してみましたが、奇妙な結果になりました (Chrome コンソールで)。

与えられた:

var a = { 'yo' : 'momma' }
var b = { 'yo' : 'cool' }
var bool = true


(bool? a : b).yo = 'LLJ'
//a is now { 'yo' : 'LLJ' }

(bool? a.yo : b.yo) = 'LLJ' //throws a reference error

最初は機能し、2 番目は失敗するのはなぜですか? (論理的には同じステートメントですよね?)

4

5 に答える 5

6

いいえ(ウィキペディアの「l-value」への言及は誤解を招くようです)-それへの参照ではなく、引数のを返しています。JavaScript の値は、直接1に割り当てることはできません。

次のことをしただけの場合:

console.log(bool ? a.yo : b.yo);
// like doing the following:
'string' = 'eee';

...文字列を取得します-文字列値/リテラル​​に割り当てることはできません。すべてのプロパティ参照は、条件演算子に渡されるときに値に変換されます。

しかし、オブジェクトであれば参照値はオブジェクトであり、オブジェクトのプロパティは参照なので問題なく動作します。

console.log(bool ? a : b); // you get an object, it's fine

ECMAScript 仕様 (JavaScript の標準バージョン) では、条件演算子から参照 (左辺値) を取得できないと規定されています。

11.12 条件演算子( ? : )

  1. LogicalOREExpressionlrefを評価した結果とします。
  2. ToBoolean(GetValue(lref))が true の 場合:
    • 最初のAssignmentExpressiontrueRefを評価した結果とします。
    • 戻るGetValue(trueRef)
  3. そうしないと
    • 2 番目のAssignmentExpressionfalseRefを評価した結果とします。
    • 戻るGetValue(falseRef)

GetValue参照を値に変換する内部関数であるため、期待どおりの参照ではなく、値を取得するのはそのためです。

1: ECMAScript の内部割り当てメソッドでは、非参照を次のものに割り当てることはできません。

8.7.2 プットバリュー(V、W)

  1. Type(V)が Reference でない場合は、ReferenceError 例外をスローします
  2. ...(残りは重要ではありません、私の強調)
于 2013-09-07T00:55:39.273 に答える
4

ウィキペディアは間違っていました。条件演算子は、左辺値ではなく右辺値を返します。

記事の歴史は非常に興味深いので、ここに要約しました。

  • 2010 年 8 月 30 日: Beginning
    JavaScript セクションが作成されました。三項演算子は JavaScript では右辺値を返すと正しく言いますが、C/C++/Java では左辺値を返すと間違って言います。C++ でのみ、三項演算子は左辺値を返します。

  • 2011 年 1 月 31 日: C で左辺値を生成できません
    C は左辺値を返さないため、JavaScript セクションから正しく削除されました。ジャバのまま。

  • 2011 年 2 月 15 日: 「修正済み」
    Java および C++ との比較が削除されました (コメントは、Java が左辺値を生成しなかったことを正しく示しています)。JavaScript が突然左辺値を返す!

  • 2011 年 3 月 7 日:希望が回復しました...
    誤った「左辺値」が「値」に変更され、値の記事(左辺値と右辺値の両方について説明しています) にリンクされています。

  • 2011 年 3 月 7 日: ...しかし長くはありません
    リンク テキストが「左辺値」に変更されました。

  • 2013 年 9 月 7 日:カンタス航空 94 Heavy に 3 つの乾杯!
    この質問のおかげで、ウィキペディアは修正されました。

于 2013-09-07T02:20:31.657 に答える
3

a.yo2 行目はorの値を参照していないためb.yo、フラット オブジェクトを参照しています。

最初の式は で終わるため、 または のいずれか.yoの値を参照することがわかります。ab

于 2013-09-07T00:55:32.140 に答える
1

ここで d が設定変数になります。

    var obj = {'d' : 1, 'd1': 2}, obj2 = {'d': 2, 'd1': 2}, bool = true;
    var dummyFn = function(obj, k, v) { obj['k'] = val; return obj; };
    (bool ? (dummyFn(obj, 'd', (obj.d = newVal + 1))) : obj).d1  = newVal = 4;
    console.log(obj.d);

コードが機能しなかった理由は、dummyFn の値を obj に置き換えることができないのと同じ理由です。参照するプロパティがないと、オブジェクトは匿名になります。

于 2013-09-07T02:07:00.777 に答える