构造 x = x ||y 的意思是?什么是双管运算符 ()?||它在JavaScript中有何不同?实际问题

我正在调试一些JavaScript,无法解释这是做什么的:||

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

这家伙为什么要用?我有时也看到它没有声明。var title = title || 'ERROR'var


答案 1

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

这是写作的简写:

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

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

a OR b

它的计算结果为 如果 是 或 。因此,如果是真的,您根本不需要检查。这称为短路布尔评估,因此:trueabtrueab

var title = title || "Error";

基本上检查是否计算到 。如果是这样,它将“返回”,否则返回。titlefalse"Error"title


答案 2

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

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

  • 如果第一个值为 ,它将检查第二个值。如果是 ,则返回,如果第二个值为 ,则返回 。falsetruetruefalsefalse
  • 如果第一个值为 ,则无论第二个值是什么,它总是返回。truetrue

所以基本上它的工作原理是这样的函数:

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 会隐式转换为布尔值。这意味着,如果该值是 falsey(例如 , , , (另请参阅 JavaScript 中的所有 falsey 值)),它将被视为 ;否则,它将被视为 .0""nullundefinedfalsetrue

所以上面的例子应该给出,因为空函数是真实的。好吧,它没有。它返回空函数。这是因为JavaScript的运算符并不像我一开始写的那样工作。它的工作方式如下:true||

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

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

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

如果将真值作为 传递,则返回 ,即真值。因此,如果您稍后在子句中使用它:xxif

(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."

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

实际问题

现在,当您知道操作员的工作原理时,您可能会自己弄清楚这意味着什么。如果是真实的,则分配给 ,因此实际上没有任何反应;否则,将 分配给 。它通常用于定义函数中的默认参数。但是,它通常被认为是一种糟糕的编程实践,因为它会阻止您将 falsey 值(不一定是 或 )作为参数传递。请考虑以下示例:||x = x || yxxxyxundefinednull

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

乍一看,它看起来是有效的。但是,如果您作为参数传递(因为它是布尔值,即可以是或)会发生什么?这将成为现实在此示例中,无法设置为 。falseflagAtruefalseflagAfalse

最好明确检查是否为 ,如下所示:flagAundefined

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

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


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

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