前者:
greeting = "hello" + (username ? username : "friend")
后者:
greeting = "hello" + (username || "friend")
下面有个回答明显对js的逻辑或操作符没有理解到位,我简单解释一下 username || "friend"
其中 username
是个标识符,可能这个变量已经定义,也可能没有定义。
逻辑或操作符的操作数可以为任意类型,并且不一定总是返回 boolean 类型,且两个操作数的值不一定全部被计算,如果左操作数为真,则直接返回左操作数的值,注意,不是返回 true
,而是左操作数的值,也就是说 4 || 0
返回的是 4
,而不是 true
,这种情况下右操作数将直接被忽略。如果左操作数为假,则直接返回右操作数的值,例如 0 || "hello world"
将会返回 "hello world"
username=''
//输出: ""
username || "friend"
//输出: "friend"
username ? username : "friend"
//输出: "friend"
你可以用浏览器自带的debugger查看一下,应该是一样的
等价的 ,只是两种不同的写法
等价的。上面那种写法其实也就是逻辑或运算。
ecmascript 规范
二元逻辑运算符 http://ecmascript.cn/#208
产生式 LogicalORExpression : LogicalORExpression || LogicalANDExpression
按照下面的过程执行 :
- 令 lref 为解释执行 LogicalORExpression 的结果 .
- 令 lval 为 GetValue(lref).
- 如果 ToBoolean(lval) 为 true ,返回 lval.
- 令 rref 为解释执行 LogicalANDExpression 的结果 .
- 返回 GetValue(rref).
LogicalANDExpressionNoIn
和 LogicalORExpressionNoIn
执行完全按照 LogicalANDExpression
和 LogicalORExpression
相同的方式,BitwiseORExpressionNoIn
和 LogicalORExpressionNoIn
替代了 BitwiseORExpression
和 LogicalORExpression
除外。
注:由 && 或者 || 运算符产生的值不是必须为Boolean类型,产生的值始终为两个运算表达式的结果之一。
条件运算符 http://ecmascript.cn/#209
产生式 ConditionalExpression : LogicalORExpression ? AssignmentExpression : AssignmentExpression
按照下面的过程执行 :
- 令 lref 为解释执行 LogicalORExpression 的结果 .
- 如果 ToBoolean(GetValue(lref)) 为 true ,那么: 令 trueRef 为解释执行第一个 AssignmentExpression 的结果 . 返回 GetValue(trueRef).
- Else 令 falseRef 为解释执行第二个 AssignmentExpression 的结果 . 返回 GetValue(falseRef).
ConditionalExpressionNoIn
执行完全按照 ConditionalExpression
相同的方式,除了AssignmentExpression
和 AssignmentExpressionNoIn
替代了第一个 AssignmentExpression
和第二个 AssignmentExpression
。
注:ECMAScript中的ConditionalExpression跟C和Java有一点点不同,它允许第二个子表达式是个Expression但是限制第三个表达式必须是ConditionalExpression。ECMAScript中这个差别的依据是可以允许允许赋值表达式出现在条件的任意一侧同时避免逗号表达式作为中间的表达式时无用且易混淆的使用方式。
这两种表达方式完全等价。
功能上一致
如果要实现同样的功能,后者更精炼.一般都会这么写.
前面那种使用场景一般是:
greeting = "hello" + (user ? user.name : "friend")
不一样!!!!!
可以从编译器性能优化的角度来看。
在诸如C、C++、java的语言里面,形如 a || b 的结构,a做真值判断结果为 true
的时候,没有必要做b的真值判断,因为根据操作符“或”的定义,只要二者有一个为真即可。因此在a真值判断结果为 true
的时候,编译器不需要计算b的值,按相应语言标准,返回a或者true。
在javascript这个语言里,“或”操作符并不一定返回boolean类型的值。上面的编译优化方式依然成立的,对于形如 a || b
的结构,编译器有以下的步骤:
- 首先判断a的真值,看其是否为“falsy”(“falsy”,即一个值为
false
、0
、""
(即空字符串),null
,undefined
,NaN
之一的时候) - 在a为非“falsy”的时候,不计算b,直接返回a(编译优化)
- 在a为“falsy”的时候,由于js的或表达式不需要返回boolean类型的值,略去b的真值判断。又因为b的值直接反映了
false || b
表达式的值,直接返回b
正因此,这两段js的写法完全等价。
更多类似的js写法,还有:
window.console && window.console.log("hello world") ;
等同于
if ( window.console ) {
window.console.log("hello world") ;
}