Javascript 三元运算符左值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18668599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 12:49:19  来源:igfitidea点击:

Javascript Ternary Operator lvalue

javascriptlvalue

提问by Ryan Dignard

I was reading about the ternary operator in different languages, and noticed something interesting in the Javascript section. http://en.wikipedia.org/wiki/%3F:#JavaScript

我正在阅读不同语言的三元运算符,并在 Javascript 部分注意到一些有趣的事情。 http://en.wikipedia.org/wiki/%3F:#JavaScript

The conditional operator in JavaScript has the same syntax and precedence structure as in the other BCPL-derived variants, but a significant difference exists in the semantics: it returns an l-value.

JavaScript 中的条件运算符与其他 BCPL 派生变体具有相同的语法和优先级结构,但语义上存在显着差异:它返回一个左值

The first sentence states that the return of the ternary in javascript is an lvalue, so I tried some examples, with odd results (in the chrome console).

第一句指出javascript中三元的返回是一个左值,所以我尝试了一些例子,结果很奇怪(在chrome控制台中)。

Given:

鉴于:

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

Why does the first work and the second fail? (Logically they're the same statements, no?)

为什么第一个工作,第二个失败?(从逻辑上讲,它们是相同的语句,不是吗?)

采纳答案by Qantas 94 Heavy

Nope (it seems that Wikipedia's reference to "l-value" is misleading) - it is returning the valueof the argument, not the referenceto it; values in JavaScript cannot be assigned to directly1.

不(似乎维基百科对“l-value”的引用具有误导性)-它返回的是参数的,而不是对它的引用;JavaScript 中的值不能直接赋值给1

If you just did the following:

如果您只是执行以下操作:

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

... you would get a string - you can't assign to a string value/literal. All property references are converted to their value when passed into the conditional operator.

...你会得到一个字符串 - 你不能分配给一个字符串值/文字。当传递给条件运算符时,所有属性引用都将转换为其值。

However, with an object, the reference value is an object, and since the property of an object is a reference, it works fine.

但是,对于一个对象,引用值是一个对象,并且由于对象的属性是一个引用,所以它工作得很好。

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

The ECMAScript specification (that's the standard version of JavaScript) says that you can't get references (i.e. a l-value) from the conditional operator:

ECMAScript 规范(这是 JavaScript 的标准版本)说你不能从条件运算符获取引用(即左值):

11.12 Conditional Operator( ? : )

  1. Let lrefbe the result of evaluating LogicalORExpression.
  2. If ToBoolean(GetValue(lref))is true, then:
    • Let trueRefbe the result of evaluating the first AssignmentExpression.
    • Return GetValue(trueRef).
  3. Else
    • Let falseRefbe the result of evaluating the second AssignmentExpression.
    • Return GetValue(falseRef).

11.12 条件运算符(? :)

  1. lref成为评估 LogicalORExpression 的结果。
  2. 如果ToBoolean(GetValue(lref))是真的,那么:
    • trueRef成为评估第一个 AssignmentExpression 的结果。
    • 返回GetValue(trueRef)
  3. 别的
    • falseRef成为评估第二个 AssignmentExpression 的结果。
    • 返回GetValue(falseRef)

GetValueis an internal function that converts a reference to a value, therefore that's why you get a value, not a reference as you expected.

GetValue是一个将引用转换为值的内部函数,因此这就是为什么你得到一个值,而不是你期望的引用。

1: The internal assignment method in ECMAScript does not allow non-references to be assigned to:

1:ECMAScript中的内部赋值方法不允许非引用赋值给:

8.7.2 PutValue(V, W)

  1. If Type(V)is not Reference, throw a ReferenceError exception.
  2. ... (the rest is unimportant, my emphasis)

8.7.2 PutValue(V, W)

  1. 如果Type(V)不是 Reference,则抛出 ReferenceError 异常
  2. ...(其余不重要,我的重点)

回答by Rottingham

Because the second line is not referencing the value of a.yoor b.yo, its referencing a flat object.

因为第二行没有引用a.yoor的值b.yo,所以它引用了一个平面对象。

The first expression ends with .yoso it knows to reference the value of either aor b.

第一个表达式以 结尾,.yo因此它知道引用aor的值b

回答by tom

Wikipedia was wrong. The conditional operator returns an r-value, not an l-value.

维基百科错了。条件运算符返回一个r-value,而不是一个l-value

The history of the article is quite interesting, so I've summarised it here:

这篇文章的历史很有趣,所以我在这里总结了一下:

  • 30 August 2010: The Beginning
    JavaScript section created. Correctly says that in JavaScript the ternary operator returns an r-value, but incorrectly says that in C/C++/Java it returns an l-value. Only in C++ the ternary operator returns an l-value.

  • 31 January 2011: Cannot yield an l-value in C
    C correctly removed from the JavaScript section because it doesn't return an l-value. Java remains.

  • 15 February 2011: "Corrected"
    The comparison to Java and C++ is removed (the comment correctly says that Java never yielded an l-value), but oh no! JavaScript suddenly returns an l-value!

  • 7 March 2011: Hope is restored...
    The incorrect "l-value" is changed to "value", linking to the Value article(which describes both l-values and r-values).

  • 7 March 2011: ...but not for long
    The link text is changed to say "l-value".

  • 7 September 2013: Three cheers for Qantas 94 Heavy!
    Thanks to this question, Wikipedia has been corrected.

  • 2010 年 8 月 30 日: 创建了Beginning
    JavaScript 部分。正确地说在 JavaScript 中三元运算符返回一个 r 值,但错误地说在 C/C++/Java 中它返回一个左值。只有在 C++ 中,三元运算符才返回左值。

  • 2011 年 1 月 31 日无法在 C
    C 中产生从 JavaScript 部分正确删除的左值,因为它不返回左值。爪哇仍然存在。

  • 2011 年 2 月 15 日“更正”
    删除了与 Java 和 C++ 的比较(注释正确地说 Java 从未产生 l 值),但是哦,不!JavaScript 突然返回一个左值!

  • 2011 年 3 月 7 日希望得到恢复...
    错误的“l-value”改为“value”,链接到Value 文章(描述了 l-values 和 r-values)。

  • 2011 年 3 月 7 日...但时间不长
    链接文本更改为“l 值”。

  • 2013 年 9 月 7 日为 Qantas 94 Heavy 欢呼三声!
    由于这个问题,维基百科已得到纠正。

回答by user1600124

Has to do with how the js is actually implemented i guess... But consider this.. (bool ? a: b) give a so the code becomes a.yo = 'LLJ', which is valid.. (bool ? a.yo : b.yo) gives what ever the string a.yo is holding. Essentially you're doing 'moma' = 'LLJ' which is invalid.

我猜这与 js 的实际实现方式有关...但是考虑一下.. (bool ? a: b) 给出 a 所以代码变成 a.yo = 'LLJ',这是有效的.. (bool ? a .yo : b.yo) 给出 a.yo 所持有的字符串。基本上你在做 'moma' = 'LLJ' 这是无效的。

回答by user1600124

Here d becomes your set variable.

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

The reason the code didn't work would be the same reason you can't replace dummyFn's value with obj. Without a property to reference the object becomes anonymous.

代码不起作用的原因与您不能用 obj 替换 dummyFn 的值的原因相同。没有属性来引用对象就变成匿名的。