JS vs PHP:与逻辑或运算符一起使用时,赋值运算符优先级 [英] JS vs PHP: assignment operator precedence when used with logical-or
问题描述
(PHP具有||
和OR
.JS仅具有||
.)
(PHP has ||
and OR
. JS only has ||
.)
JS .根据 MDN ||
的优先级高于=
.所以这行不通:
JS. According to MDN ||
has higher precedence than =
. So this doesn't work:
a || a = 1;
因为它的评估为:
(a || a) = 1;
这将导致分配中的左侧无效".我明白那个.那是有道理的.
which results in an "Invalid left-hand side in assignment". I understand that. That makes sense.
PHP.根据 PHP.net 对于PHP:||
在=
之前的工作方式相同.但是,我一直都在使用它:
PHP. According to PHP.net it works the same for PHP: ||
before =
. However, I use this all the time:
$a || $a = 1;
为什么它可以在PHP中运行?最重要的是:PHP的OR
优先级低于=
,因此它们不应该这样做:
Why does it work in PHP?? And to top it off: PHP's OR
has lower precedence than =
, so these shouldn't do the same:
$a || $a = 1;
$a OR $a = 1;
但是他们确实... https://3v4l.org/UWXMd
but they do... https://3v4l.org/UWXMd
我认为JS的||
根据MDN的表工作,而PHP的OR
类似于PHP的表,但PHP的||
不应像它那样工作.
I think JS' ||
works according to MDN's table, and PHP's OR
works like PHP's table, but PHP's ||
shouldn't work like it does.
这是另一个怪异的PHP怪癖吗?
Is this yet another weird PHP quirk?
手册中也提到了这一点:
The manual also mentions this:
尽管
=
的优先级低于大多数其他运算符,但PHP仍将允许类似于以下内容的表达式:if (!$a = foo())
,在这种情况下,foo()
的返回值将放入$a
.
Although
=
has a lower precedence than most other operators, PHP will still allow expressions similar to the following:if (!$a = foo())
, in which case the return value offoo()
is put into$a
.
优先级表指示PHP应该评估(!$a) = foo()
,这没有意义并且应该失败,但是PHP将其评估为!($a = foo())
,因为它喜欢异常.
The precedence table dictates PHP should evaluate (!$a) = foo()
, which makes no sense and should fail, but PHP evaluates it as !($a = foo())
, because it loves exceptions.
后续问题:您认为if ( $d = $c && $e = $b && $f = $a )
是什么? https://3v4l.org/3P2hN 我听不懂...我确实了解第二和第三个情况(使用and
),只是没有发生在第一个情况中.
Follow-up question: What do you think if ( $d = $c && $e = $b && $f = $a )
does? https://3v4l.org/3P2hN I don't get it... I do understand the second and third case (with and
), just not what happens in the first.
推荐答案
According to zend_language_parser.y the code is parsed equivalently to $a || ($a = 1)
and $a or ($a = 1)
in each case, respectively.
正如melpomene总结的那样,赋值产生是 not 在表达式上的后缀二元运算符;相对而言,分配运算符是受限产品,其中左侧必须是variable
产品.
As summarized by melpomene, the assignment productions are not infix binary operators over expressions; rather assignment operators are restricted productions where the left-hand side must be a variable
production.
每个借用的报价:
因此,PHP以唯一可能的方式解析表达式.
Thus PHP parses the expression in the only possible way..
有关优先顺序的文档正确.适用的地方.
The documentation is correct about the precedence .. where it applies.
因此,$a || $a = 1
遵循以下(反向)的结果:
Thus $a || $a = 1
follows the (reversed) productions of:
variable "||" variable "=" expr
variable "||" expr_without_variable
expr "||" expr
expr
!$a = foo()
的情况与之类似,并且在遵循(反转)后会被解析为!($a = foo())
:
The case of !$a = foo()
is similar and is parsed as !($a = foo())
after following the (reversed) productions:
"!" variable "=" expr
"!" expr_without_variable
"!" expr
expr
现在,$d = $c && $e = $b && $f = $a
怎么样?即使&&
确实的优先级高于分配,它也不会被解析为($d = $c) && ..
.它实际上被解析为$d = ($c && ($e = ..))
,依此类推,由精明的读者完成.
Now, how about $d = $c && $e = $b && $f = $a
? It is not parsed as ($d = $c) && ..
even though the &&
does have a higher precedence than the assignment. It is actually parsed as $d = ($c && ($e = ..))
and so on, to be completed by the astute reader.
虽然可能不会引起人们的注意,但这种差异能够产生不同的结果:
While it might not be casually noticed, this difference is capable of producing varying results:
$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
因此,在将赋值运算符与优先级更高的运算符混合使用时,通常应使用括号,尤其是当这样的结果可能不清楚时.
Parenthesis should thus generally be used when mixing assignment operators with operators of higher precedence, especially when the result of such may be .. unclear.
乍一看似乎不一致,但这是一个定义明确的语法-但是技术细节被掩盖在一些相当普通的文档中;并且这些规则与其他类似C语法的语言中的规则有细微的区别.文档中缺少官方的EBNF并没有帮助.
As inconsistent as this may initially seem, it is a well-defined grammar - but the technical details are buried behind some fairly layman documentation; and the rules differ subtly from those in other C-syntax-like languages. The lack of an official EBNF in the documentation doesn't help.
尽管有解析细节,但从评估的角度来看,$a || $a = ..
代码(是有效且定义明确的语法)应保持定义良好,因为必须出现或"的左侧由于保证了短路,因此在权利之前.
Despite the parsing details, the $a || $a = ..
code (which is valid and well-defined syntax) should remain well-defined from an evaluation viewpoint as the left side of the 'or' must occur prior to the right due to guaranteed short-circuiting.
For contrast, in JavaScript, a || a = 1
is parsed as (a || a) = 1
- which is also syntactically 'valid' code - per the ECMAScript Grammar Rules. However, a || a
does not yield a valid Reference Specification Type and thus a runtime ReferenceError is thrown.
这篇关于JS vs PHP:与逻辑或运算符一起使用时,赋值运算符优先级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!