簡體   English   中英

什么是構造 x = x || 你是什​​么意思?

[英]What does the construct x = x || y mean?

我正在調試一些 JavaScript 並且無法解釋這是什么|| 做:

function (title, msg) {
  var title = title || 'Error';
  var msg   = msg || 'Error on Request';
}

為什么這家伙使用var title = title || 'ERROR' var title = title || 'ERROR' 我有時也會看到它沒有var聲明。

這意味着title參數是可選的。 因此,如果您不帶參數調用該方法,它將使用默認值"Error"

這是寫作的簡寫:

if (!title) {
  title = "Error";
}

這種布爾表達式的速記技巧在 Perl 中也很常見。 用表達式:

a OR b

它的計算結果為true如果任abtrue 所以如果a是真的,你根本不需要檢查b 這稱為短路布爾評估,因此:

var title = title || "Error";

基本上檢查title是否評估為false 如果是,則“返回” "Error" ,否則返回title

什么是雙管道運算符 ( || )?

雙管道運算符 ( || ) 是邏輯OR運算符 大多數語言中,它的工作方式如下:

  • 如果第一個值為false ,則檢查第二個值。 如果為true ,則返回true ,如果第二個值為false ,則返回false
  • 如果第一個值是true ,它總是返回true ,無論第二個值是什么。

所以基本上它的工作原理是這樣的:

function or(x, y) {
  if (x) {
    return true;
  } else if (y) {
    return true;
  } else {
    return false;
  }
}

如果還是不明白,請看這張表:

      | true   false  
------+---------------
true  | true   true   
false | true   false  

換句話說,只有當兩個值都為假時才為假。

它在 JavaScript 中有什么不同?

JavaScript 有點不同,因為它是一種松散類型的語言 在這種情況下,這意味着您可以使用|| 具有非布爾值的運算符。 雖然沒有意義,但您可以將此運算符用於例如函數和對象:

(function(){}) || {}

那里會發生什么?

如果值不是布爾值,JavaScript 會隱式轉換為 boolean 這意味着如果值是假的(例如0""nullundefined (另見JavaScript 中的所有假值)),它將被視為false 否則它被視為true

所以上面的例子應該給出true ,因為空函數是真的。 好吧,它沒有。 它返回空函數。 那是因為 JavaScript 的|| 操作符不像我一開始寫的那樣工作。 它的工作方式如下:

  • 如果第一個值為falsey ,則返回第二個值
  • 如果第一個值是值,則返回第一個值

驚訝? 實際上,它與傳統的||是“兼容的” 操作員。 可以寫成如下函數:

function or(x, y) {
  if (x) {
    return x;
  } else {
    return y;
  }
}

如果您將真值作為x傳遞,它會返回x ,即真值。 因此,如果您稍后在if子句中使用它:

(function(x, y) {
  var eitherXorY = x || y;
  if (eitherXorY) {
    console.log("Either x or y is truthy.");
  } else {
    console.log("Neither x nor y is truthy");
  }
}(true/*, undefined*/));

你會得到"Either x or y is truthy." .

如果x是假的,則eitherXorY將是y 在這種情況下,您將得到"Either x or y is truthy." 如果y是truthy; 否則你會得到"Neither x nor y is truthy"

實際問題

現在,當你知道如何|| 運算符有效,您可能可以自己弄清楚x = x || y是什么 x = x || y意思。 如果x為真,則x被分配給x ,所以實際上什么也沒發生; 否則y分配給x 它通常用於定義函數中的默認參數。 但是,它通常被認為是一種糟糕的編程實踐,因為它會阻止您將 falsey 值(不一定是undefinednull )作為參數傳遞。 考慮以下示例:

function badFunction(/* boolean */flagA) {
  flagA = flagA || true;
  console.log("flagA is set to " + (flagA ? "true" : "false"));
}

乍一看,它看起來很有效。 但是,如果您將false作為flagA參數傳遞(因為它是布爾值,即可以是truefalse )會發生什么? 這將成為true 在此示例中,無法將flagA設置為false

顯式檢查flagA是否為undefined會是一個更好的主意,如下所示:

function goodFunction(/* boolean */flagA) {
  flagA = typeof flagA !== "undefined" ? flagA : true;
  console.log("flagA is set to " + (flagA ? "true" : "false"));
}

雖然它更長,但它總是有效並且更容易理解。


您還可以將 ES6 語法用於默認函數參數,但請注意,它不適用於舊瀏覽器(如 IE)。 如果你想支持這些瀏覽器,你應該使用Babel轉譯你的代碼。

另請參閱MDN 上的邏輯運算符

如果未設置標題,則使用 'ERROR' 作為默認值。

更通用:

var foobar = foo || default;

讀取:將 foobar 設置為foodefault 你甚至可以多次鏈接它:

var foobar = foo || bar || something || 42;

稍微解釋一下這個...

|| 運算符是邏輯or運算符。 如果第一部分為真,則結果為真,如果第二部分為真,則結果為真,如果兩部分都為真,則結果為真。 為了清楚起見,這里有一張表:

 X | Y | X || Y 
---+---+--------
 F | F |   F    
---+---+--------
 F | T |   T    
---+---+--------
 T | F |   T    
---+---+--------
 T | T |   T    
---+---+--------

現在注意到這里的一些東西了嗎? 如果X為真,則結果始終為真。 因此,如果我們知道X為真,我們根本不必檢查Y 因此,許多語言為邏輯or (和邏輯)實現了“短路”評估器, and來自另一個方向。 他們檢查第一個元素,如果這是真的,他們根本不會檢查第二個元素。 結果(在邏輯方面)是相同的,但在執行方面,如果第二個元素的計算成本很高,則可能存在巨大差異。

那么這和你的例子有什么關系呢?

var title   = title || 'Error';

讓我們來看看。 title元素被傳遞給您的函數。 在 JavaScript 中,如果不傳入參數,則默認為空值。 同樣在 JavaScript 中,如果您的變量是空值,則邏輯運算符將其視為假。 因此,如果在給定標題的情況下調用此函數,則它是一個非假值,因此分配給局部變量。 然而,如果它沒有被賦予一個值,它就是一個空值,因此是假的。 然后邏輯or運算符計算第二個表達式並返回“錯誤”。 所以現在局部變量被賦予值“錯誤”。

這是因為在 JavaScript 中實現了邏輯表達式。 它不返回正確的布爾值( truefalse ),而是返回根據某些規則給出的值,即什么被認為等同於true什么被認為等同於false 查找您的 JavaScript 參考以了解 JavaScript 在布爾上下文中認為是對還是錯。

基本上,它檢查||之前的值是否評估為真。 如果是,就取這個值,如果不是,就取||后面的值 .

它將取||之后的值的值 (就目前我所記得的):

  • 不明確的
  • 錯誤的
  • 0
  • ''(空或空字符串)

雙管代表邏輯“或”。 當“未設置參數”時,情況並非如此,因為如果您有這樣的代碼,那么嚴格地在 JavaScript 中:

function foo(par) {
}

然后調用

foo()
foo("")
foo(null)
foo(undefined)
foo(0)

不等價。

雙管道 (||) 將第一個參數轉換為布爾值,如果結果布爾值為真 - 進行賦值,否則將分配正確的部分。

如果您檢查未設置參數,這很重要。

比方說,我們有一個函數 setSalary,它有一個可選參數。 如果用戶不提供參數,則應使用默認值 10。

如果您像這樣進行檢查:

function setSalary(dollars) {
    salary = dollars || 10
}

這將為如下調用提供意想不到的結果:

setSalary(0)

它仍將按照上述流程設置 10。

雖然Cletus 的回答是正確的,但我覺得應該添加更多關於 JavaScript 中“評估為假”的細節。

var title = title || 'Error';
var msg   = msg || 'Error on Request';

不僅要檢查是否提供了 title/msg,還要檢查它們中的任何一個是否為false 即以下之一:

  • 錯誤的。
  • 0(零)
  • ""(空字符串)
  • 空值。
  • 不明確的。
  • NaN(一個特殊的數值,表示非數值!)

所以在行

var title = title || 'Error';

如果 title 為真(即不為假,所以 title = "titleMessage" 等),則布爾 OR (||) 運算符已找到一個“真”值,這意味着它的計算結果為真,因此它短路並返回真實值(標題)。

如果 title 為假(即上面的列表之一),則布爾 OR (||) 運算符已找到“假”值,現在需要計算運算符的另一部分“錯誤”,其計算結果為真,因此被返回。

看起來(在一些快速的螢火蟲控制台實驗之后)如果運算符的兩邊都評估為假,它會返回第二個“假”運算符。

IE

return ("" || undefined)

返回未定義,這可能是為了讓您在嘗試將標題/消息默認為“”時使用此問題中詢問的行為。 即運行后

var foo = undefined
foo = foo || ""

foo 將設置為“”

雙管操作員

這個例子可能有用:

var section = document.getElementById('special');
if(!section){
     section = document.getElementById('main');
}

它也可以是:

var section = document.getElementById('special') || document.getElementById('main');

|| 是布爾OR運算符。 由於在JavaScript中,不確定,NULL,0,假被視為falsy值。

簡單來說就是

true || true = true
false || true = true
true || false = true
false || false = false

undefined || "value" = "value"
"value" || undefined = "value"
null || "value" = "value"
"value" || null = "value"
0 || "value" = "value"
"value" || 0 = "value"
false || "value" = "value"
"value" || false = "value"

為了對我之前所說的所有內容進行一些解釋,我應該舉一些例子來理解邏輯概念。

var name = false || "Mohsen"; # name equals to Mohsen
var family = true || "Alizadeh" # family equals to true

這意味着如果左側評估為真語句,它將被完成,左側將被返回並分配給變量。 在其他情況下,右側將被退回和分配。

運營商有相反的結構如下圖所示。

var name = false && "Mohsen" # name equals to false
var family = true && "Alizadeh" # family equals to Alizadeh

引用:“構造 x = x || y 是什么意思?”

分配默認值。

這意味着將 y 的默認值提供給 x ,以防 x 仍在等待其值但尚未收到它或被故意省略以回退到默認值。

我還必須補充一點:這種速記方式令人厭惡。 它誤用了一個意外的解釋器優化(如果第一個操作為真,則不打擾第二個操作)來控制分配。 該用途與操作員的目的無關。 我不相信它應該被使用。

例如,我更喜歡使用三元運算符進行初始化,

var title = title?title:'Error';

這使用單行條件操作來實現其正確目的。 它仍然以真實性玩着難看的游戲,但是,這就是 JavaScript 給你的。

暫無
暫無

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

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