JavaScript có đánh giá "Ngắn mạch" không?


101

Tôi muốn biết JavaScript có đánh giá "ngắn mạch" như Toán tử && trong C # hay không. Nếu không, tôi muốn biết liệu có giải pháp nào phù hợp để áp dụng không.


2
Không có gì. Tôi đã thêm https://www.google.com/search?q=site:stackoverflow.com+%slàm lối tắt tìm kiếm (Chrome / Firefox) để tăng tốc độ tìm kiếm.
Rob W

Đây cũng là câu trả lời cho câu hỏi của tôi developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
GibboK

Câu trả lời:


118

Có, JavaScript có đánh giá "ngắn mạch".

if (true == true || foo.foo){
    // Passes, no errors because foo isn't defined.
}

Bản thử trực tiếp

if (false && foo.foo){
    // Passes, no errors because foo isn't defined.
}

Bản thử trực tiếp


8
Vì vậy, ngắn mạch nó là tiêu chuẩn trong JS?
GibboK

1
Cảm ơn gdoron, xin vui lòng giúp tôi hiểu ... trong C # Tôi cũng có nhà điều hành nhị phân như & vì vậy cả hai toán hạng phải đúng để vượt qua, thay vì với && trong C
GibboK

1
@GibboK. Sau đó, rõ ràng, không thể có một Short-circuitvới toán tử logic đó. Chỉ cần thử nó cho mình. Sử dụng bản demo của tôi.
gdoron đang hỗ trợ Monica

2
@GibboK: Kiểm tra tham chiếu nhà điều hành này . Và vâng, cũng có một toán tử AND nhị phân trong JS.
Bergi

5
@GibboK. CÓ trong tiêu chuẩn! Nhưng nhận xét tốt, như trong thời gian của phép thuật biên dịch JIT trong việc triển khai javascript, người ta thực sự muốn biết liệu một cái gì đó là "tiêu chuẩn", hoặc có khả năng phải thực hiện. Cách một tuyên bố tình trạng với Binary nhà khai thác logic được đánh giá và (ngắn curcuit) là một hành vi tiêu chuẩn ecma-international.org/ecma-262/5.1/#sec-11.11
humanityANDpeace

23

Câu trả lời này đi sâu vào chi tiết về cách hoạt động trong JavaScript, với tất cả các chủ đề có liên quan và cũng như quyền ưu tiên của toán tử, nếu bạn đang tìm kiếm một định nghĩa nhanh và đã hiểu cách hoạt động của hiện tượng đoản mạch, tôi khuyên bạn nên kiểm tra các câu trả lời khác.


Những gì chúng tôi (nghĩ rằng chúng tôi) biết cho đến nay:

Trước tiên, hãy kiểm tra hành vi mà tất cả chúng ta đều quen thuộc, bên trong if()khối, nơi chúng ta sử dụng &&để kiểm tra xem hai thứ có phải là true:

if (true && true) {
   console.log('bar');
} 

Bây giờ, bản năng đầu tiên của bạn có lẽ là nói: 'À vâng, khá đơn giản, mã thực thi câu lệnh nếu cả hai expr1expr2được đánh giá là true'

Vâng, có và không. Bạn nói đúng về mặt kỹ thuật, đó là hành vi bạn đã mô tả, nhưng đó không chính xác là cách mã được đánh giá và chúng tôi sẽ cần nghiên cứu sâu hơn để hiểu đầy đủ.


Chính xác &&và được ||giải thích như thế nào ?:

Đã đến lúc xem xét "dưới mui xe của engine ". Hãy xem xét ví dụ thực tế này:

function sanitise(x) {
  if (isNaN(x)) {
    return NaN;
  }
  return x;
}

let userinput = 0xFF; // as an example
const res = sanitise(userinput) && userinput + 5

console.log(res);

Kết quả là 260.. nhưng tại sao? Để có câu trả lời, chúng ta cần hiểu cách đánh giá ngắn mạch hoạt động như thế nào.

Theo Định nghĩa MDN , &&toán tử trong expr1 && expr2được thực thi như sau:

Nếu expr1có thể được chuyển đổi thành true, trả về expr2; khác, trả về expr1.

Vì vậy, điều này có nghĩa là, trong ví dụ thực tế của chúng tôi, const resgiá trị được đánh giá theo cách sau:

  1. Mời expr1-sanitise(0xFF)
  2. 0xFF là một số thập lục phân hợp lệ cho 250, nếu không, tôi sẽ trả lại NaN
  3. Các expr1trở một "truthy" giá trị, thời gian để thực hiện expr2 (nếu không tôi sẽ dừng lại như NaNlà falsy)
  4. userinputnó là sự thật (một con số), tôi có thể thêm +5vào nó
  • "Truthy" có nghĩa là biểu thức có thể được đánh giá là đúng. Dưới đây là danh sách các truthyfalsy biểu thức.

Vì vậy, ở đây, chúng tôi có thể tránh các ifkhối bổ sung và isNaNkiểm tra thêm bằng cách sử dụng &&toán tử đơn giản .


Cách nó thực sự hoạt động:

Bây giờ, ít nhất chúng ta nên có một bức tranh về cách các nhà điều hành hoạt động. Quy tắc chung là:

  • (some falsy expression) && expr sẽ đánh giá thành biểu hiện giả dối
  • (some truthy expression) || expr sẽ đánh giá biểu hiện trung thực

Dưới đây là một số ví dụ khác để hiểu rõ hơn:

function a() { console.log('a'); return false; }
function b() { console.log('b'); return true; }

if ( a() && b() ){
     console.log('foobar'); 
}

//Evaluates a() as false, stops execution.

function a() { console.log('a'); return false; }
function b() { console.log('b'); return true; }

if ( a() || b() ){
     console.log('foobar'); 
}

/* 1. Evaluates a() as false
   2. So it should execute expr2, which is `b()`
   3. b() returned as true, executing statement `console.log('foobar');`
*/


Một điều khó chịu cuối cùng, nhưng rất quan trọng [Quyền ưu tiên của nhà điều hành]:

Tốt, hy vọng bạn hiểu được nó! Điều cuối cùng chúng ta cần biết là một quy tắc về ưu tiên toán tử, đó là:

  • Các &&nhà điều hành luôn được thực hiện trước khi các ||nhà điều hành.

Hãy xem xét ví dụ sau:

function a() { console.log('a'); return true;}
function b() { console.log('b'); return false;}
function c() { console.log('c'); return false;}

console.log(a() || b() && c());

// returns a() and stops execution

Điều này sẽ trả về, có lẽ gây nhầm lẫn cho một số như a(). Lý do khá đơn giản, chỉ là thị giác của chúng ta đang đánh lừa chúng ta, bởi vì chúng ta đã quen với việc đọc từ trái sang phải. Hãy xem xét console.log()những điều được và không được và tập trung hoàn toàn vào đánh giá

true || false && false

Bây giờ để quấn lấy đầu của bạn xung quanh điều này:

  1. Chúng tôi đã nói rằng &&nhà điều hành có quyền ưu tiên, vì vậy nó được đánh giá là đầu tiên. Để giúp chúng ta hình dung rõ hơn về việc đánh giá, hãy nghĩ đến định nghĩa

    expr1 && expr2

    Ở đâu:

    • expr2false
    • expr1true || false
  2. Vì vậy, đó là phần khó khăn, bây giờ true || falseđược đánh giá (phía expr1- bên trái của &&).

    • Đưa ra ||toán tử dừng thực thi nếu expr1 || expr2trong expr1đánh giá là đúng, expr1thì toán tử được thực thi và thực thi mã dừng.
  3. Giá trị trả về là true

Chà .. điều đó khá phức tạp, tất cả chỉ vì một vài quy tắc và ngữ nghĩa kỳ lạ. Nhưng hãy nhớ, bạn luôn có thể thoát khỏi ưu tiên toán tử với ()- giống như trong toán học

function a() { console.log('a'); return true;}
function b() { console.log('b'); return false;}
function c() { console.log('c'); return false;}

console.log((a() || b()) && c());

/* 1. The () escape && operator precedence
   2. a() is evaluated as false, so expr2 (c()) to be executed
   3. c()  
*/


Tôi sẽ 1) không sử dụng từ "trình biên dịch". "engine" chính xác hơn. 2) Không được nói về expr1expr2 hay condition1hay bất cứ điều gì, mà chỉ là khó hiểu. Quyết định cho một, bạn cũng có thể giới thiệu các biến cục bộ, ví dụ. const expr1 = true; if(expr1 && ...)
Jonas Wilms

@JonasWilms cảm ơn bạn đã đóng góp ý kiến, đã sửa đổi câu trả lời cho phù hợp.
Samuel Hulla

1
Điều này vẫn không trả lời trực tiếp câu hỏi được đặt ra.
Kevin B

7
Đây là sản phẩm tốt nhất "câu trả lời tuyệt vời mà không trả lời rõ ràng cho câu hỏi" mà tôi đã từng nhìn thấy ...
Gerardo Furtado

1
Đây là câu trả lời đúng với lời giải thích sâu sắc, nên được đánh dấu là chấp nhận và ủng hộ nhiều hơn hiện tại!
Alexander Kim
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.