2015-09-19 18 views
15

(PHP có ||OR JS chỉ có ||..)JS vs PHP: phân công điều hành được ưu tiên khi sử dụng với logic hoặc

JS. Theo MDN|| có mức độ ưu tiên cao hơn =. Vì vậy, điều này không làm việc:

a || a = 1; 

vì nó đánh giá là:

(a || a) = 1; 

mà kết quả trong một "phía bên tay trái không hợp lệ trong chuyển nhượng". Tôi hiểu điều đó. Điều đó có ý nghĩa.

PHP. Theo PHP.net, nó hoạt động tương tự cho PHP: || trước =. Tuy nhiên, tôi sử dụng nó mọi lúc:

$a || $a = 1; 

Tại sao nó hoạt động trong PHP ?? Và để đầu nó đi: PHP OR có độ ưu tiên thấp hơn =, do đó, những không nên làm như vậy:

$a || $a = 1; 
$a OR $a = 1; 

nhưng họ làm ... https://3v4l.org/UWXMd

Tôi nghĩ rằng JS' || công trình theo MDN của và OR của PHP hoạt động giống như bảng của PHP, nhưng || của PHP không hoạt động giống như vậy.

Đây có phải là một quirk PHP kỳ lạ khác không?

Tài liệu hướng dẫn cũng đề cập đến điều này:

Mặc dù = có độ ưu tiên thấp hơn hầu hết các nhà khai thác khác, PHP vẫn sẽ cho phép biểu thức tương tự như sau: if (!$a = foo()), trong trường hợp giá trị trả về của foo() được đưa vào $a.

bảng

Các ưu tiên mệnh lệnh PHP nên đánh giá (!$a) = foo(), mà làm cho không có ý nghĩa và nên thất bại, nhưng PHP đánh giá nó như !($a = foo()), bởi vì nó rất thích hợp ngoại lệ.

Câu hỏi tiếp theo: Bạn nghĩ gì if ($d = $c && $e = $b && $f = $a)? https://3v4l.org/3P2hN Tôi không hiểu ... Tôi hiểu trường hợp thứ hai và thứ ba (với and), không phải điều gì xảy ra trong lần đầu tiên.

+0

Hướng dẫn sử dụng PHP cũng nói là Ưu tiên toán tử và tính liên kết chỉ xác định cách biểu thức được nhóm lại, chúng không chỉ định thứ tự đánh giá. PHP không (trong trường hợp chung) xác định thứ tự một biểu thức được đánh giá và mã giả định một thứ tự đánh giá cụ thể cần tránh, bởi vì hành vi có thể thay đổi giữa các phiên bản của PHP hoặc tùy thuộc vào mã xung quanh. – CY5

+0

@ CY5 Sự khác nhau giữa nhóm và đánh giá là gì? Nhóm làm gì mà không có thứ tự đánh giá? – Rudie

+0

PHP! = JS. Có câu trả lời của bạn. –

Trả lời

13

Theo số zend_language_parser.y mã được phân tích cú pháp tương ứng với số $a || ($a = 1)$a or ($a = 1) trong mỗi trường hợp.

Như được tóm tắt bởi melpomene, các bài tập chỉ định là không các toán tử nhị phân mã nhị phân trên biểu thức; thay vì nhà điều hành chuyển nhượng là các sản phẩm bị hạn chế nơi bên tay trái phải là một sản xuất variable.

mỗi một borrowed quote:

Như vậy PHP phân tích các biểu hiện trong cách duy nhất có thể ..

Các tài liệu là đúng về ưu tiên .. nơi nó áp dụng.


Như vậy sau các tác phẩm (đảo ngược) của:

variable "||" variable "=" expr 
variable "||" expr_without_variable 
expr "||" expr 
expr 

Trường hợp của !$a = foo() là giống nhau và được phân tách như !($a = foo()) sau khi làm theo tác phẩm (đảo ngược):

"!" variable "=" expr 
"!" expr_without_variable 
"!" expr     
expr 

Bây giờ, làm thế nào về $d = $c && $e = $b && $f = $a? Đó là không phải được phân tích cú pháp là ($d = $c) && .. mặc dù &&hiện có mức độ ưu tiên cao hơn so với bài tập. Nó thực sự được phân tích cú pháp là $d = ($c && ($e = ..)) và vân vân, được hoàn thành bởi người đọc sắc sảo.

Trong khi nó có thể không được nhận thấy tình cờ, sự khác biệt này có khả năng sản xuất các kết quả khác nhau:

$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 

ngoặc nên do đó thường được sử dụng khi trộn các toán tử gán với những hoạt động ưu tiên cao hơn, đặc biệt là khi kết quả của ví dụ có thể .. không rõ ràng.

Không nhất quán như ban đầu, đây là ngữ pháp được xác định rõ - nhưng các chi tiết kỹ thuật được chôn sau một số tài liệu công bằng; và các quy tắc khác nhau một cách tinh tế so với các quy tắc khác trong các ngôn ngữ giống như cú pháp C. Việc thiếu một EBNF chính thức trong tài liệu không giúp ích gì.


Mặc dù các chi tiết phân tích cú pháp, các $a || $a = .. mã (mà hợp lệ và cũng xác định cú pháp) nên vẫn được xác định rõ từ một quan điểm đánh giá như phía bên trái của 'hoặc' phải xảy ra trước thời điểm phải do guaranteed short-circuiting.


Đối Ngược lại, trong JavaScript, a || a = 1 được phân tách như (a || a) = 1 - đó cũng là cú pháp mã 'hợp lệ' - theo ECMAScript Grammar Rules. Tuy nhiên, a || a không cung cấp Loại Đặc tả Tham chiếu hợp lệ và do đó thời gian chạy Tham chiếuMỗi được ném.

+1

Theo ngữ pháp đó, '=' không phải là một toán tử infix thực: Không có vấn đề gì ở bên trái của nó, nó chỉ lấy một biến. Nó hoạt động giống như toán tử meta-prefix: '$ foo =' parses giống như toán tử tiền tố cho tất cả các biến '$ foo'. – melpomene

+0

@melpomene Đó là mấu chốt của nó: tay trái của '=' bị giới hạn trong một biến (trái ngược với một expr). – user2864740

+0

Vì vậy, PHP và JS có quy tắc ưu tiên toán tử rất giống nhau, chỉ có các quy tắc phân tích cú pháp khác nhau? Điều đó có ý nghĩa. Tôi đã quá treo lên trên bảng ưu tiên. Cảm ơn! – Rudie

1

Đối với followup câu hỏi của bạn: if ($d = $c && $e = $b && $f = $a) là giống như:

$d = $c; 
if($d) { 
    $e = $b; 
    if($e) { 
     $f = $a; 
     if($f) { 
      ... 
     } 
    } 
} 

Tôi giả sử bạn biết điều này, nhưng một số trong những câu hỏi là khó hiểu đối với tôi, vì vậy tôi sẽ đề cập đến nó ... = là một toán tử gán, không phải toán tử so sánh. if($a = $b) không kiểm tra nếu $ a và $ b là như nhau, nó làm cho $ a bằng $ b, sau đó kiểm tra xem $ a có đánh giá là đúng hay không. if($a == $b) kiểm tra xem hai biến có giống nhau hay không.

+1

Tại sao nó được phân tích như vậy? Theo bảng ưu tiên, nó phải là '$ d = (($ c && $ e) = (($ b && $ f) = $ a))'. – melpomene

+0

Đoán của tôi là cùng một lý do mà '" 1 "+ 1 + 1,5' đánh giá là 3,5 chứ không phải là ném lỗi về việc cố gắng thêm một chuỗi và một số nguyên và một phao.PHP là một ngôn ngữ kịch bản và (họ nói với tôi) tương đối tha thứ như là một kết quả. PHP không đánh giá && trước khi = bởi vì nó trong một câu lệnh if và điều đó sẽ không có ý nghĩa (hoặc ít ý nghĩa hơn). Trong thực tế, nó thậm chí sẽ không đánh giá các tùy chọn thứ hai hoặc thứ ba nếu đánh giá đầu tiên sai (đó là lý do tại sao trong ví dụ của bạn $ e và $ f vẫn là -1). Nếu bạn đang ở trong quá trình đánh giá chính xác, tôi khuyên bạn nên dựa vào dấu ngoặc đơn: chúng đáng tin cậy hơn. – Stevish

+0

Tôi đã chỉnh sửa khối mã của tôi để phản ánh chính xác hơn cách PHP xử lý '=' và '&&' trong điều kiện if. – Stevish

-1

Khái niệm $a || $a = 1; tương đương với điều này:

if ($a != true) { 
    $a = 1; 
} 

Một biến thể rất phổ biến trên ý tưởng được sử dụng cho người nghèo-mans gỡ lỗi:

$debug = true; 

// Thousands of lines of code 

$debug && printf("Foo: {$foo}"); 

// More code 

$debug && printf("Bar: {$bar}"); 

Trong mô hình này, chỉ có $debug nhu cầu tuyên bố được đặt thành true/false để bật/tắt gỡ lỗi. Tôi không ủng hộ loại gỡ lỗi này, nhưng tôi đã nhìn thấy nó một vài lần.

+1

Vui lòng trả lời điểm OPs: cho biết là * không * được phân tích cú pháp như vậy. Ngoài ra, '||' là * không * giống như '&& 'một cách hợp lý. – user2864740

+0

(Vâng, "không nên" thay vì.) – user2864740

+1

Khối mã đầu tiên của bạn là sai: 'if ($ a == true) {'. Ý bạn là 'sai'. Và tôi biết điều này. Tuy nhiên, không trả lời câu hỏi của tôi. – Rudie

Các vấn đề liên quan