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

IT技术 javascript parameters optional-parameters or-operator
2021-01-12 01:30:58

我正在调试一些 JavaScript 并且无法解释它的||作用:

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

这家伙为什么用var title = title || 'ERROR'我有时也会在没有var声明的情况下看到它

6个回答

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

这是写作的简写:

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

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

a OR b

它评估为trueifabis true所以如果a是真的,你根本不需要检查b这称为短路布尔评估,因此:

var title = title || "Error";

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

这不是答案,我同意最后一条评论,它甚至不是可选的。这个答案的任何部分都不是正确的,即使是 Perl 参考,因为 Perl 语句实际上使 SENSE 并以完全不同的方式进行评估。JS 是一种更加“转换”的布尔逻辑方法的 eval,我也发现读/写更令人困惑。下面标题为“什么是双管运算符”的答案实际上是正确的答案。
2021-03-10 01:30:58
抱歉挑剔,但参数不是可选的,参数被检查
2021-04-04 01:30:58

什么是双管道运算符 ( ||)?

双管道运算符 ( ||) 是逻辑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, "", null, undefined(另请参阅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."ify为真;否则你会得到"Neither x nor y is truthy".

实际问题

现在,当您知道||运算符的工作原理时,您可能会自己弄明白x = x || y什么意思。如果x为真,x则分配给x,因此实际上什么也没发生;否则y分配给x它通常用于定义函数中的默认参数。但是,它通常被认为是一种糟糕的编程习惯,因为它会阻止您将错误值(不一定是undefinednull)作为参数传递考虑以下示例:

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

乍一看,它看起来很有效。但是,如果您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"));
}

虽然它更长,但它总是有效并且更容易理解。


您还可以将 ES6 语法用于默认函数参数,但请注意,它不适用于旧浏览器(如 IE)。如果你想支持这些浏览器,你应该使用Babel转译你的代码

另请参阅MDN 上的逻辑运算符

2021 年重温:使用无效合并运算符 ( ??)
2021-03-11 01:30:58
FWIW,我会将代码片段编写为function or(x, y) { if (x) return x; else return y; }. 这基本上是在所有语言 AFAIK 中所做的,包括严格和松散类型的,包括 JavaScript。[本次讨论忽略短路] 不同语言之间的唯一区别是在什么条件下if (x)为真。[在严格类型的语言中,if (x)仅适用于true,因此return x与 相同return true。]
2021-03-12 01:30:58
+1,简而言之:title = title || 'Error'意味着if (title) { title = title; } else { title = 'Error'; }
2021-03-13 01:30:58
我实际上不同意“虽然它没有意义”的说法。例如,我知道该行不会在 C 中编译,但是如果您来自 Ruby 或什至 Groovy,则很容易理解。在 Ruby 中,您可以将它表达得更短,如title ||= 'Error'.
2021-03-28 01:30:58
+1 - 迄今为止最正确和最完整的答案。而且,对于那些有这个问题的人(包括我们一些不熟悉 JS 的资深程序员)当然应该把整个答案的大部分集中在这一行上:“虽然这没有意义”,因为这种“loosley 类型”永远没有意义对于我们这些在没有它的情况下长大的人。对我们来说,布尔运算符就是这样,并且仅此而已......并且无论谁认为在阅读/编写代码时必须停下来思考将非布尔值转换为布尔值的古怪转换是个好主意的人,那天忘记吃药了!:)
2021-04-03 01:30:58

如果未设置标题,则使用“错误”作为默认值。

更通用:

var foobar = foo || default;

读取:将 foobar 设置为foodefault你甚至可以多次链接它:

var foobar = foo || bar || something || 42;
我发现它令人困惑,因为变量具有相同的名称。当他们不这样做时要容易得多。
2021-04-07 01:30:58

稍微解释一下这个...

||操作是logical-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
  • ''(空或空字符串)
假|| 空 || 未定义 || 0 || '' || '你忘了空'
2021-03-27 01:30:58