JS vs PHP:与逻辑或一起使用时的赋值运算符优先级
JS vs PHP: assignment operator precedence when used with logical-or
(PHP有||
和OR
。JS只有||
。)
JS. 根据 MDN ||
的优先级高于 =
。所以这不起作用:
a || a = 1;
因为它被评估为:
(a || a) = 1;
结果是 "Invalid left-hand side in assignment"。我明白那个。有道理。
PHP. 根据 PHP.net 它对 PHP 的作用相同:||
在 =
之前.但是,我一直使用这个:
$a || $a = 1;
为什么它在 PHP 中有效??最重要的是:PHP 的 OR
的优先级低于 =
,因此它们不应该这样做:
$a || $a = 1;
$a OR $a = 1;
但他们确实... https://3v4l.org/UWXMd
我认为 JS 的 ||
根据 MDN 的 table 工作,而 PHP 的 OR
的工作方式类似于 PHP 的 table,但是 PHP 的 ||
不应该像它那样工作。
这是另一个奇怪的 PHP 怪癖吗?
手册中也提到了这一点:
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 of foo()
is put into $a
.
优先级 table 指示 PHP 应该计算 (!$a) = foo()
,这没有意义并且应该失败,但是 PHP 将其计算为 !($a = foo())
,因为它喜欢例外。
后续问题:你认为if ( $d = $c && $e = $b && $f = $a )
是做什么的? https://3v4l.org/3P2hN 我不明白...我理解第二种和第三种情况(使用 and
),只是不了解第一种情况。
关于您的后续问题: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即可enable/disable调试。 我不是提倡这种类型的调试,但我已经看过很多次了。
根据 zend_language_parser.y,代码在每种情况下分别等效于 $a || ($a = 1)
和 $a or ($a = 1)
解析。
正如 melpomene 总结的那样,赋值产生式 不是 表达式上的中缀二元运算符;相反,赋值运算符是受限产生式,其中左侧必须是variable
产生式。
根据 borrowed quote:
Thus PHP parses the expression in the only possible way..
关于优先级的文档正确.. 它适用的地方。
因此 $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
怎么样?它 not 被解析为 ($d = $c) && ..
即使 &&
does 的优先级高于赋值。它实际上被解析为 $d = ($c && ($e = ..))
等等,由精明的人完成 reader.
虽然可能不会随便注意到,但这种差异能够产生不同的结果:
$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 = ..
代码( 是 有效且定义明确的语法)从评估的角度来看应该保持良好定义,因为左侧由于 guaranteed short-circuiting.
,'or' 的一部分必须出现在右边之前
相比之下,在 JavaScript 中,a || a = 1
被解析为 (a || a) = 1
- 根据 ECMAScript Grammar Rules,这在语法上也是 'valid' 代码。但是,a || a
不会产生有效的参考规范类型,因此会抛出 runtime ReferenceError。
(PHP有||
和OR
。JS只有||
。)
JS. 根据 MDN ||
的优先级高于 =
。所以这不起作用:
a || a = 1;
因为它被评估为:
(a || a) = 1;
结果是 "Invalid left-hand side in assignment"。我明白那个。有道理。
PHP. 根据 PHP.net 它对 PHP 的作用相同:||
在 =
之前.但是,我一直使用这个:
$a || $a = 1;
为什么它在 PHP 中有效??最重要的是:PHP 的 OR
的优先级低于 =
,因此它们不应该这样做:
$a || $a = 1;
$a OR $a = 1;
但他们确实... https://3v4l.org/UWXMd
我认为 JS 的 ||
根据 MDN 的 table 工作,而 PHP 的 OR
的工作方式类似于 PHP 的 table,但是 PHP 的 ||
不应该像它那样工作。
这是另一个奇怪的 PHP 怪癖吗?
手册中也提到了这一点:
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
.
优先级 table 指示 PHP 应该计算 (!$a) = foo()
,这没有意义并且应该失败,但是 PHP 将其计算为 !($a = foo())
,因为它喜欢例外。
后续问题:你认为if ( $d = $c && $e = $b && $f = $a )
是做什么的? https://3v4l.org/3P2hN 我不明白...我理解第二种和第三种情况(使用 and
),只是不了解第一种情况。
关于您的后续问题: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即可enable/disable调试。 我不是提倡这种类型的调试,但我已经看过很多次了。
根据 zend_language_parser.y,代码在每种情况下分别等效于 $a || ($a = 1)
和 $a or ($a = 1)
解析。
正如 melpomene 总结的那样,赋值产生式 不是 表达式上的中缀二元运算符;相反,赋值运算符是受限产生式,其中左侧必须是variable
产生式。
根据 borrowed quote:
Thus PHP parses the expression in the only possible way..
关于优先级的文档正确.. 它适用的地方。
因此 $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
怎么样?它 not 被解析为 ($d = $c) && ..
即使 &&
does 的优先级高于赋值。它实际上被解析为 $d = ($c && ($e = ..))
等等,由精明的人完成 reader.
虽然可能不会随便注意到,但这种差异能够产生不同的结果:
$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 = ..
代码( 是 有效且定义明确的语法)从评估的角度来看应该保持良好定义,因为左侧由于 guaranteed short-circuiting.
相比之下,在 JavaScript 中,a || a = 1
被解析为 (a || a) = 1
- 根据 ECMAScript Grammar Rules,这在语法上也是 'valid' 代码。但是,a || a
不会产生有效的参考规范类型,因此会抛出 runtime ReferenceError。