(PHP有||
和OR
)JS只有||
)
JS。根据MDN, ||
优先级高于=
。所以这行不通:
a || a = 1;
因为它被计算为:
(a || a) = 1;
会导致"赋值时左侧无效"。我理解。有道理。
PHP。根据PHP.net,它的工作原理与PHP相同:||
在=
之前。但是,我一直使用这个:
$a || $a = 1;
为什么它在PHP中工作??最重要的是:PHP的OR
的优先级比=
低,所以它们不应该做同样的事情:
$a || $a = 1;
$a OR $a = 1;
但是他们……https://3v4l.org/UWXMd
我认为JS的||
根据MDN的表工作,PHP的OR
像PHP的表一样工作,但PHP的||
不应该像它那样工作。
这是另一个奇怪的PHP怪癖吗?
手册也提到了这一点:
尽管
=
的优先级比大多数其他操作符低,PHP仍然允许类似于以下的表达式:if (!$a = foo())
,在这种情况下,foo()
的返回值被放入$a
。
优先级表指示PHP应该计算(!$a) = foo()
,这没有意义,应该失败,但是PHP将其计算为!($a = foo())
,因为它喜欢异常。
后续问题:你认为if ( $d = $c && $e = $b && $f = $a )
是做什么的?https://3v4l.org/3P2hN我不明白…我确实理解第二种和第三种情况(and
),只是不像第一种情况。
根据zend_language_parser。在每种情况下,代码分别被解析为$a || ($a = 1)
和$a or ($a = 1)
。
正如melpomene所总结的,赋值结果是而不是中缀二进制操作符在表达式上;rather 赋值操作符是受限生成,其中左侧必须是variable
生成。
引用:
因此PHP以唯一可能的方式解析表达式。
文档正确关于优先级…
因此$a || $a = 1
遵循(相反的)结果:
variable "||" variable "=" expr
variable "||" expr_without_variable
expr "||" expr
expr
!$a = foo()
的情况与此类似,在(反向)生成之后被解析为!($a = foo())
:
"!" variable "=" expr
"!" expr_without_variable
"!" expr
expr
那么,$d = $c && $e = $b && $f = $a
呢?即使&&
确实比赋值具有更高的优先级,也不会被解析为($d = $c) && ..
。它实际上被解析为$d = ($c && ($e = ..))
等等,由精明的读者来完成。
虽然它可能不会被不经意地注意到,但这种差异能够产生不同的结果:
$a = (($c = 1) && ($d = 0));
var_dump($a, $c, $d); // => false, 1, 0
$b = ($e = 1 && $f = 0); // => $b = ($e = (1 && ($f = 0)));
var_dump($b, $e, $f); // => false, false, 0
因此,在将赋值操作符与更高优先级的操作符混合使用时,通常应使用括号,特别是当其结果可能为…不清楚。
虽然最初看起来不一致,但它是一个定义良好的语法-但是技术细节隐藏在一些相当外行的文档后面;这些规则与其他类似c语法的语言略有不同。文档中缺少官方的EBNF也没有帮助。
尽管有解析细节,但从求值的角度来看,$a || $a = ..
代码(是有效且定义良好的语法)应该保持良好的定义,因为"或"的左侧必须在右侧之前出现,因为保证了短路。
相比之下,在JavaScript中,a || a = 1
被解析为(a || a) = 1
——这也是语法上"有效"的代码——根据ECMAScript语法规则。但是,a || a
没有产生有效的引用规范类型,因此会抛出运行时 ReferenceError。
关于你的后续问题:if ( $d = $c && $e = $b && $f = $a )
与:
$d = $c;
if($d) {
$e = $b;
if($e) {
$f = $a;
if($f) {
...
}
}
}
我想你知道这个,但是有些问题让我很困惑,所以我就提一下…=是赋值操作符,而不是比较操作符。if($a = $b)
不检查$a和$b是否相同,它使$a等于$b,然后检查$a是否为真。if($a == $b)
检查两个变量是否相同
表达式$a || $a = 1;
等价于:
if ( $a != true ) {
$a = 1;
}
这个想法的一个非常常见的变体是用于穷人调试:
$debug = true;
// Thousands of lines of code
$debug && printf("Foo: {$foo}");
// More code
$debug && printf("Bar: {$bar}");
在这个范例中,只有$debug
语句需要设置为true/false来打开/关闭调试。我并不提倡这种调试方式,但是我已经见过很多次了