构造x = x ||是什么 你的意思是?

opH*_*AME 230 javascript parameters optional-parameters or-operator

我正在调试一些JavaScript,并不能解释这||是做什么的?

function (title, msg) {
  var title = title || 'Error';
  var msg   = msg || 'Error on Request';
}
Run Code Online (Sandbox Code Playgroud)

有人可以给我一个提示,为什么这个人正在使用var title = title || 'ERROR'?我有时也会在没有var声明的情况下看到它.

cle*_*tus 201

这意味着title参数是可选的.因此,如果您调用没有参数的方法,它将使用默认值"Error".

这是写作的简写:

if (!title) {
  title = "Error";
}
Run Code Online (Sandbox Code Playgroud)

这种带有布尔表达式的速记技巧在Perl中也很常见.用表达式:

a OR b
Run Code Online (Sandbox Code Playgroud)

它的计算结果true,如果任一a或者btrue.所以,如果a是真的,你根本不需要检查b.这称为短路布尔评估,因此:

var title = title || "Error";
Run Code Online (Sandbox Code Playgroud)

基本上检查是否title评估false.如果是,则"返回" "Error",否则返回title.

  • 这不是答案,我同意最后的评论它甚至不是可选的.这个答案的任何部分都不正确,即使Perl引用也是如此,因为Perl语句实际上使得SENSE以完全不同的方式进行评估.JS是一个更加"转换"的布尔逻辑方法,我也觉得读/写更加混乱.下面标题为"什么是双管道操作员"的答案实际上是一个正确的答案. (4认同)
  • 很抱歉挑剔,但参数不是可选的,参数被检查 (3认同)

Mic*_*ski 182

什么是双管操作符(||)?

双管运算符(||)是逻辑OR运算符.在大多数语言中,它的工作方式如下:

  • 如果第一个值是false,则检查第二个值.如果是true,则返回true,如果是false,则返回false.
  • 如果第一个值是true,则true无论第二个值是什么,它总是返回.

所以基本上它就像这个函数一样:

function or(x, y) {
  if (x) {
    return true;
  } else if (y) {
    return true;
  } else {
    return false;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您仍然不明白,请查看此表:

      | true   false  
------+---------------
true  | true   true   
false | true   false  
Run Code Online (Sandbox Code Playgroud)

换句话说,当两个值都为假时,它才是假的.

它在JavaScript中有何不同?

JavaScript有点不同,因为它是一种松散类型的语言.在这种情况下,这意味着您可以使用||不是布尔值的运算符.虽然没有意义,但您可以将此运算符用于例如函数和对象:

(function(){}) || {}
Run Code Online (Sandbox Code Playgroud)

那里发生了什么?

如果值不是布尔值,则JavaScript将隐式对话设置为布尔值.这意味着,如果该值是falsey(例如0,"",null,undefined(还参见在JavaScript中所有falsey值)),它将被视为false; 否则它被视为true.

所以上面的例子应该给出true,因为空函数是真的.嗯,事实并非如此.它返回空函数.那是因为JavaScript的||运算符不像我在开头写的那样工作.它的工作方式如下:

  • 如果第一个值为falsey,则返回第二个值.
  • 如果第一个值是真实的,则返回第一个值.

惊讶吗?实际上,它与传统||运营商"兼容" .它可以写成以下函数:

function or(x, y) {
  if (x) {
    return x;
  } else {
    return y;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果你传递一个真值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*/));
Run Code Online (Sandbox Code Playgroud)

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

如果x是假的,那eitherXorY就是y.在这种情况下,你会得到"Either x or y is truthy."if y是真的; 否则你会得到"Neither x nor y is truthy".

实际的问题

现在,当你知道||操作员的工作方式时,你可以自己弄明白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"));
}
Run Code Online (Sandbox Code Playgroud)

它看起来很有效.但是,如果你false作为flagA参数传递会发生什么(因为它是布尔值,即可以是truefalse)?它会成为true.在此示例中,无法设置flagAfalse.

明确检查是否flagA是这样的话会更好undefined:

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

虽然它更长,它总是有效,而且更容易理解.


您还可以将ES6语法用于默认函数参数,但请注意,它在旧版浏览器(如IE)中不起作用.如果您想支持这些浏览器,您应该使用Babel来转换代码.

另请参见MDN上的逻辑运算符.

  • +1 - 到目前为止最正确和完整的答案.而且,对于那些与这个问题(我们一些新的JS老将编码器包含的)当然应该关注最有效地利用这条线这整个的回答:"虽然这是没有意义的",因为这"loosley输入"根本不会意义我们这些没有它的人.对于我们来说,布尔逻辑运算符仅仅是和只有......和任何人没有想过这将是一个不错的主意,有通过非布尔值的一些古怪的转换停下来思考,以布尔值,而读/写代码,那天忘了带药吧!:) (12认同)
  • +1,简而言之:`title = title || “错误”表示`if(title){title = title; } else {title ='错误'; }` (2认同)

eri*_*ert 28

如果未设置title,请使用"ERROR"作为默认值.

更通用的:

var foobar = foo || default;
Run Code Online (Sandbox Code Playgroud)

阅读:将foobar设置为foodefault.你甚至可以多次链接这个:

var foobar = foo || bar || something || 42;
Run Code Online (Sandbox Code Playgroud)


JUS*_*ION 14

再解释一下......

||操作是logical- or操作.如果第一部分为真,则结果为true;如果第二部分为真,则结果为true;如果两部分均为真,则结果为true.为清楚起见,这里是一个表格:

 X | Y | X || Y 
---+---+--------
 F | F |   F    
---+---+--------
 F | T |   T    
---+---+--------
 T | F |   T    
---+---+--------
 T | T |   T    
---+---+--------
Run Code Online (Sandbox Code Playgroud)

现在注意点什么?如果X为true,则结果始终为true.因此,如果我们知道这X是真的,我们根本不需要检查Y.因此,许多语言为逻辑or(和and来自另一个方向的逻辑)实现"短路"评估器.他们检查第一个元素,如果这是真的,他们根本不打扰检查第二个元素.结果(逻辑上)是相同的,但就执行而言,如果第二个元素的计算成本很高,则可能存在巨大差异.

那么这与你的例子有什么关系呢?

var title   = title || 'Error';
Run Code Online (Sandbox Code Playgroud)

我们来看看.该title元素在你的函数传递.在JavaScript中,如果未传入参数,则默认为空值.同样在JavaScript中,如果您的变量是空值,则逻辑运算符将其视为false.因此,如果使用给定的标题调用此函数,则它是非假值,因此分配给局部变量.但是,如果没有给出值,则它是空值,因此是假的.然后逻辑or运算符计算第二个表达式并返回"Error".所以现在局部变量的值为'Error'.

这是因为JavaScript中的逻辑表达式的实现.它不会返回一个正确的布尔值(truefalse),而是返回它在某些规则下给出的值,该值被认为等同于true什么以及被认为等价于什么false.查找您的JavaScript参考,以了解JavaScript在布尔上下文中认为是真或假的.


小智 8

虽然Cletus 的回答是正确的,但我觉得应该添加更多关于 JavaScript 中“评估为假”的细节。

var title = title || 'Error';
var msg   = msg || 'Error on Request';
Run Code Online (Sandbox Code Playgroud)

不仅要检查是否提供了 title/msg,还要检查它们中的任何一个是否为false。即以下之一:

  • 错误的。
  • 0(零)
  • ""(空字符串)
  • 空值。
  • 不明确的。
  • NaN(一个特殊的数值,表示非数值!)

所以在行

var title = title || 'Error';
Run Code Online (Sandbox Code Playgroud)

如果 title 为真(即不为假,所以 title = "titleMessage" 等),则布尔 OR (||) 运算符已找到一个“真”值,这意味着它的计算结果为真,因此它短路并返回真实值(标题)。

如果 title 为假(即上面的列表之一),则布尔 OR (||) 运算符已找到“假”值,现在需要计算运算符的另一部分“错误”,其计算结果为真,因此被返回。

看起来(在一些快速的萤火虫控制台实验之后)如果运算符的两边都评估为假,它会返回第二个“假”运算符。

IE

return ("" || undefined)
Run Code Online (Sandbox Code Playgroud)

返回未定义,这可能是为了让您在尝试将标题/消息默认为“”时使用此问题中询问的行为。即运行后

var foo = undefined
foo = foo || ""
Run Code Online (Sandbox Code Playgroud)

foo 将设置为“”


Mor*_*dur 7

基本上它会检查||之前的值 计算结果为true,如果是,则采用此值,如果不是,则采用||之后的值.

在||之后取值的值 (就目前我所记得的):

  • 未定义
  • 0
  • ''(空或空字符串)


Jur*_*riy 7

双管代表逻辑"OR".当"参数未设置"时,情况并非如此,因为如果你有这样的代码,严格来说在javascript中:

function foo(par) {
}
Run Code Online (Sandbox Code Playgroud)

然后打电话

foo()
foo("")
foo(null)
foo(undefined)
foo(0)
Run Code Online (Sandbox Code Playgroud)

不等同.

双管道(||)会将第一个参数转换为布尔值,如果结果布尔值为true,则执行赋值,否则它将分配正确的部分.

如果您检查未设置的参数,这很重要.

比方说,我们有一个函数setSalary,它有一个可选参数.如果用户未提供参数,则应使用默认值10.

如果你做这样的检查:

function setSalary(dollars) {
    salary = dollars || 10
}
Run Code Online (Sandbox Code Playgroud)

这会在电话上给出意想不到的结果

setSalary(0) 
Run Code Online (Sandbox Code Playgroud)

它仍将按照上述流程设置10.


cho*_*ise 5

双管操作员

这个例子可能有用:

var section = document.getElementById('special');
if(!section){
     section = document.getElementById('main');
}
Run Code Online (Sandbox Code Playgroud)

它也可以是:

var section = document.getElementById('special') || document.getElementById('main');
Run Code Online (Sandbox Code Playgroud)


Shi*_*pta 5

|| 是布尔OR运算符。由于在JavaScript中,不确定,NULL,0,假被视为falsy值。

简单来说就是

true || true = true
false || true = true
true || false = true
false || false = false
Run Code Online (Sandbox Code Playgroud)
undefined || "value" = "value"
"value" || undefined = "value"
null || "value" = "value"
"value" || null = "value"
0 || "value" = "value"
"value" || 0 = "value"
false || "value" = "value"
"value" || false = "value"
Run Code Online (Sandbox Code Playgroud)