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
Javascript Ternary Operator lvalue
提问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( ? : )
- Let
lref
be the result of evaluating LogicalORExpression.- If
ToBoolean(GetValue(lref))
is true, then:
- Let
trueRef
be the result of evaluating the first AssignmentExpression.- Return
GetValue(trueRef)
.- Else
- Let
falseRef
be the result of evaluating the second AssignmentExpression.- Return
GetValue(falseRef)
.
11.12 条件运算符(? :)
- 让
lref
成为评估 LogicalORExpression 的结果。- 如果
ToBoolean(GetValue(lref))
是真的,那么:
- 让
trueRef
成为评估第一个 AssignmentExpression 的结果。- 返回
GetValue(trueRef)
。- 别的
- 让
falseRef
成为评估第二个 AssignmentExpression 的结果。- 返回
GetValue(falseRef)
。
GetValue
is 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)
- If
Type(V)
is not Reference, throw a ReferenceError exception.- ... (the rest is unimportant, my emphasis)
8.7.2 PutValue(V, W)
- 如果
Type(V)
不是 Reference,则抛出 ReferenceError 异常。- ...(其余不重要,我的重点)
回答by Rottingham
Because the second line is not referencing the value of a.yo
or b.yo
, its referencing a flat object.
因为第二行没有引用a.yo
or的值b.yo
,所以它引用了一个平面对象。
The first expression ends with .yo
so it knows to reference the value of either a
or b
.
第一个表达式以 结尾,.yo
因此它知道引用a
or的值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 的值的原因相同。没有属性来引用对象就变成匿名的。