What does the construct x = x || y mean?
我正在调试一些javascript,无法解释这个
1 2 3 4 | function (title, msg) { var title = title || 'Error'; var msg = msg || 'Error on Request'; } |
有人能给我个提示吗,为什么这家伙要用
这意味着
这是书写的简写:
1 2 3 | if (!title) { title ="Error"; } |
这种布尔表达式的速记技巧在Perl中也很常见。使用表达式:
1 | a OR b |
如果
1 | var title = title ||"Error"; |
基本上检查
什么是双管操作员(
双管运算符(
- 如果第一个值是
false ,则检查第二个值。如果是true ,返回true ,如果是false ,返回false 。 - 如果第一个值是
true ,则无论第二个值是什么,它始终返回true 。
所以基本上它是这样工作的:
1 2 3 4 5 6 7 8 9 | function or(x, y) { if (x) { return true; } else if (y) { return true; } else { return false; } } |
如果你还是不明白,看看这张表:
1 2 3 4 | | true false ------+--------------- true | true true false | true false |
换句话说,只有当两个值都为假时才是假的。
它在javascript中有什么不同?JavaScript有点不同,因为它是一种松散类型的语言。在这种情况下,它意味着可以使用值不是布尔值的
1 | (function(){}) || {} |
那里发生了什么?
如果值不是布尔值,则javascript会隐式地与布尔值进行对话。即如果值为假(如
所以上面的例子应该给出
- 如果第一个值为假,则返回第二个值。
- 如果第一个值为truthy,则返回第一个值。
惊讶?实际上,它与传统的
1 2 3 4 5 6 7 | function or(x, y) { if (x) { return x; } else { return y; } } |
如果您将一个真实值作为
1 2 3 4 5 6 7 8 | (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*/)); |
你得到了
如果
现在,当你知道
1 2 3 4 | function badFunction(/* boolean */flagA) { flagA = flagA || true; console.log("flagA is set to" + (flagA ?"true" :"false")); } |
乍一看是有效的。但是,如果您将
最好明确检查
1 2 3 4 | function goodFunction(/* boolean */flagA) { flagA = typeof flagA !=="undefined" ? flagA : true; console.log("flagA is set to" + (flagA ?"true" :"false")); } |
虽然它更长,但它总是有效的,更容易理解。
您也可以使用ES6语法作为默认函数参数,但请注意,它在旧的浏览器(如IE)中不起作用。如果你想支持这些浏览器,你应该使用babel开发你的代码。
另请参见MDN上的逻辑运算符。
如果未设置标题,请使用"错误"作为默认值。
更通用:
1 | var foobar = foo || default; |
读取:将foobar设置为
1 | var foobar = foo || bar || something || 42; |
再解释一下……
1 2 3 4 5 6 7 8 9 10 | X | Y | X || Y ---+---+-------- F | F | F ---+---+-------- F | T | T ---+---+-------- T | F | T ---+---+-------- T | T | T ---+---+-------- |
注意到了吗?如果
那么这和你的例子有什么关系呢?
1 | var title = title || 'Error'; |
让我们看看这个。
这是因为在JavaScript中实现了逻辑表达式。它不返回正确的布尔值(
双管代表逻辑"或"。当"参数未设置"时,情况并非如此,因为如果您有这样的代码,则严格在JavaScript中:
1 2 | function foo(par) { } |
然后调用
1 2 3 4 5 | foo() foo("") foo(null) foo(undefined) foo(0) |
不是等效的。
double pipe()将第一个参数强制转换为boolean,如果结果boolean为true,则执行赋值,否则它将指定正确的部分。
如果检查未设置的参数,这很重要。
例如,我们有一个函数setsalary,它有一个可选参数。如果用户不提供参数,则应使用默认值10。
如果您这样做:
1 2 3 | function setSalary(dollars) { salary = dollars || 10 } |
这将在调用时产生意外结果,如
1 | setSalary(0) |
它仍将按照上述流程设置10。
基本上,它检查计算值之前的值是否为真,如果为真,则取该值;如果不是,则取计算值之后的值。
它将取之后的值(据我所知):
- 未定义
- 假
- 零
- ""(空或空字符串)
为了给我之前所说的一切增加一些解释,我应该给你一些例子来理解逻辑概念。
1 2 | var name = false ||"Mohsen"; # name equals to Mohsen var family = true ||"Alizadeh" # family equals to true |
它意味着,如果左侧被评估为一个真语句,它将完成,左侧将被返回并分配给变量。在其他情况下,将返回并分配右侧。
和运算符的结构相反,如下所示。
1 2 | var name = false &&"Mohsen" # name equals to false var family = true &&"Alizadeh" # family equals to Alizadeh |
虽然Cletus的答案是正确的,但我觉得应该在javascript中添加更多关于"评估为假"的细节。
1 2 | var title = title || 'Error'; var msg = msg || 'Error on Request'; |
不仅要检查是否提供了标题/msg,而且还要检查其中一个是否有问题。即以下其中一种:
- false.
- 0 (zero)
- "" (empty string)
- null.
- undefined.
- NaN (a special Number value meaning Not-a-Number!)
所以在这条线上
1 | var title = title || 'Error'; |
如果title是truthy(即,不是falsy,所以title="titleMessage"等),那么布尔或()运算符找到一个"true"值,这意味着它的计算结果为true,因此它短路并返回真值(title)。
如果标题不正确(即上面列表中的一个),则布尔或()运算符找到了一个"false"值,现在需要计算运算符"error"的另一部分,该部分的计算结果为true,因此返回。
如果操作员的两边都评估为假,那么(经过一些快速的Firebug控制台实验之后),它会返回第二个"falsy"操作员。
即
1 | return ("" || undefined) |
返回未定义,这可能允许您在尝试将标题/消息默认为"时使用此问题中询问的行为"。即跑步后
1 2 | var foo = undefined foo = foo ||"" |
foo将设置为"
双管操作工
这个例子有用吗?
1 2 3 4 | var section = document.getElementById('special'); if(!section){ section = document.getElementById('main'); } |
也可以
1 | var section = document.getElementById('special') || document.getElementById('main'); |
引述:"构造x=x y是什么意思?"
指定默认值。
这意味着提供默认值y到x,如果X仍在等待它的值,但还没有收到它,或者故意忽略它,以便返回到默认值。
我还得再加一件事:这一点点的速记是可憎的。它错误地使用了一个意外的解释器优化(如果第一个操作是正确的,则不必担心第二个操作)来控制一个分配。这种用法与操作员的目的无关。我认为它不应该被使用。
我更喜欢使用三元运算符进行初始化,例如,
1 | var title = title?title:'Error'; |
它使用一行条件操作来实现正确的目的。它仍然用Truthinness玩难看的游戏,但这是你的javascript。