簡體   English   中英

JavaScript 有“短路”評估嗎?

[英]Does JavaScript have “Short-circuit” evaluation?

我想知道 JavaScript 是否有像 C# 中的 && 運算符這樣的“短路”評估。 如果沒有,我想知道是否有一種可行的解決方法可以采用。

是的,JavaScript 有“短路”評估。

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

現場演示

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

現場演示

這個答案非常詳細地介紹了 JavaScript 中如何工作,以及所有問題和相關主題,例如運算符優先級,如果您正在尋找快速定義並且已經了解短路的工作原理,我會推薦檢查其他答案。


到目前為止我們(認為我們)知道的:

首先讓我們檢查一下我們都熟悉的行為,在if()塊中,我們使用&&來檢查這兩件事是否為true

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

現在,您的第一直覺可能會說: “啊,是的,很簡單,如果expr1expr2都被評估為true ,代碼就會執行語句”

嗯,是和不是。 您在技術上是正確的,這就是您所描述的行為,但這並不是評估代碼的方式,我們需要深入研究才能完全理解。


&&||究竟是怎樣的解釋?:

是時候看看“ 引擎的”了。 讓我們考慮這個實際例子:

 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);

結果是260 .. 但為什么呢? 為了得到答案,我們需要了解短路評估是如何工作的。

MDN定義&&運營商在expr1 && expr2是從動地執行:

如果expr1可以轉換為true ,則返回expr2 否則,返回expr1

所以這意味着,在我們的實際示例中, const res的評估方式如下:

  1. 調用expr1 - sanitise(0xFF)
  2. 0xFF是 250 的有效十六進制數,否則我將返回NaN
  3. expr1返回一個“真實”值,是執行expr2時間(否則我會停止,因為NaN是假的)
  4. 由於userinput是truthy(數字),我可以添加+5
  • “Truthy”意味着表達式可以被評估為真。 這是一個truthyfalsy表達式的列表。

所以在這里,我們能夠避免額外的if塊,並使用&&運算符的簡單用法進一步檢查isNaN


它是如何工作的:

到現在為止,我們至少應該了解運算符的工作原理。 通用規則是:

  • (some falsy expression) && expr將計算為假表達式
  • (some truthy expression) || expr (some truthy expression) || expr將評估為真表達式

以下是一些進一步的示例,以便更好地理解:

 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');` */


最后一件討厭但非常重要的事情[運算符優先級]:

很好,希望你能掌握它! 我們需要知道的最后一件事是關於運算符優先級的規則,即:

  • &&運算符總是在||之前執行操作員。

考慮以下示例:

 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

這將作為a()返回,可能會令人困惑。 原因很簡單,只是我們的視力在欺騙我們,因為我們習慣於從左到右閱讀。 讓我們把console.log()和什么不出來,完全專注於評估

true || false && false

現在讓你的頭腦圍繞這個:

  1. 我們說&&運算符具有優先級,因此它被評估為第一個。 為了幫助我們更好地想象評估,想想定義

    expr1 && expr2

    在哪里:

    • expr2false
    • expr1true || false true || false
  2. 所以這是棘手的部分,現在是true || false true || false被評估( expr1 - &&左側)。

    • 鑒於|| 運算符在expr1 || expr2停止執行 expr1 || expr2expr1計算結果為truthy,所述expr1被執行,代碼執行停止。
  3. 返回值為true

嗯..這很棘手,因為很少有奇怪的規則和語義。 但請記住,您始終可以使用()來逃避運算符優先級 -就像在數學中一樣

 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() */

這個想法是從左到右讀取邏輯表達式,如果左條件的值足以得到總值,則不會處理和評估右條件。 一些非常簡單的例子:

 function test() { const caseNumber = document.querySelector('#sel').value; const userChoice = () => confirm('Press OK or Cancel'); if (caseNumber === '1') { console.log (1 === 1 || userChoice()); } else if (caseNumber === '2') { console.log (1 === 2 && userChoice()); } else if (caseNumber === '3') { console.log (1 === 2 || userChoice()); } else if (caseNumber === '4') { console.log (1 === 1 && userChoice()); } else if (caseNumber === '5') { console.log (userChoice() || 1 === 1); } else if (caseNumber === '6') { console.log (userChoice() && 1 === 2); } }
 <label for="sel">Select a number of a test case and press "RUN!":</label> <br><select id="sel"> <option value="">Unselected</option> <option value="1">Case 1</option> <option value="2">Case 2</option> <option value="3">Case 3</option> <option value="4">Case 4</option> <option value="5">Case 5</option> <option value="6">Case 6</option> </select> <button onclick="test()">RUN!</button>

上面的前兩種情況將分別打印到控制台結果truefalse ,您甚至不會看到要求您按“確定”或“取消”的模式窗口,因為左側條件足以定義總結果。 相反,在情況 3-6 中,您將看到模態窗口要求您選擇,因為前兩者取決於正確的部分(即您的選擇),而后兩者 - 無論聚合這些表達式的值不取決於您的選擇——因為首先讀取左條件。 因此,根據要首先處理的條件從左到右放置條件非常重要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM