[英]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
如果任a
或b
為true
。 所以如果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 有點不同,因為它是一種松散類型的語言。 在這種情況下,這意味着您可以使用||
具有非布爾值的運算符。 雖然沒有意義,但您可以將此運算符用於例如函數和對象:
(function(){}) || {}
如果值不是布爾值,JavaScript 會隱式轉換為 boolean 。 這意味着如果值是假的(例如0
、 ""
、 null
、 undefined
(另見JavaScript 中的所有假值)),它將被視為false
; 否則它被視為true
。
所以上面的例子應該給出true
,因為空函數是真的。 好吧,它沒有。 它返回空函數。 那是因為 JavaScript 的||
操作符不像我一開始寫的那樣工作。 它的工作方式如下:
驚訝? 實際上,它與傳統的||
是“兼容的” 操作員。 可以寫成如下函數:
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 值(不一定是undefined
或null
)作為參數傳遞。 考慮以下示例:
function badFunction(/* boolean */flagA) {
flagA = flagA || true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
乍一看,它看起來很有效。 但是,如果您將false
作為flagA
參數傳遞(因為它是布爾值,即可以是true
或false
)會發生什么? 這將成為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 設置為foo
或default
。 你甚至可以多次鏈接它:
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 中實現了邏輯表達式。 它不返回正確的布爾值( true
或false
),而是返回根據某些規則給出的值,即什么被認為等同於true
什么被認為等同於false
。 查找您的 JavaScript 參考以了解 JavaScript 在布爾上下文中認為是對還是錯。
基本上,它檢查||
之前的值是否評估為真。 如果是,就取這個值,如果不是,就取||
后面的值 .
它將取||
之后的值的值 (就目前我所記得的):
雙管代表邏輯“或”。 當“未設置參數”時,情況並非如此,因為如果您有這樣的代碼,那么嚴格地在 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.