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

时间:2010-05-10 10:58:20

标签: javascript parameters optional-parameters or-operator

我正在调试一些JavaScript,无法解释这个||的作用?

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

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

12 个答案:

答案 0 :(得分:183)

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

这是写作的简写:

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

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

a OR b

如果trueab,则评估为true。因此,如果a为真,则根本不需要检查b。这称为短路布尔评估,所以:

var title = title || "Error";

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

答案 1 :(得分:158)

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

双管道运算符(||)是逻辑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会将隐式会话设置为布尔值。这意味着如果值为false(例如0""nullundefined(另请参阅All falsey values in JavaScript)),则会将其视为{ {1}};否则它被视为false

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

  • 如果第一个值为 falsey ,则返回第二个值
  • 如果第一个值为 truthy ,则会返回第一个值

惊讶?实际上,它是"兼容"使用传统的||运算符。它可以写成以下函数:

||

如果您将真实值传递为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

实际问题

现在,当您知道"Neither x nor y is truthy"运算符的工作原理时,您可以自己了解||的含义。如果x = x || y是真实的,x被分配给x,那么实际上没有任何反应;否则x被分配给y。它通常用于定义函数中的默认参数。但是,它通常被认为是糟糕的编程习惯,因为它会阻止您将falsey值(不一定是xundefined)作为参数传递。请考虑以下示例:

null

第一眼看上去很有效。但是,如果您将function badFunction(/* boolean */flagA) { flagA = flagA || true; console.log("flagA is set to " + (flagA ? "true" : "false")); } 作为false参数传递(因为它的布尔值,即可以是flagAtrue),会发生什么? 它将成为false在此示例中,无法将true设置为flagA

最好明确检查false是否flagA,如下:

undefined

虽然时间更长,但它始终有效并且更容易理解。

您也可以使用the ES6 syntax for default function parameters,但请注意,它不适用于较旧的浏览器(如IE)。如果您想支持这些浏览器,则应使用Babel来转换代码。

另见Logical Operators on MDN

答案 2 :(得分:28)

如果未设置title,请使用“ERROR”作为默认值。

更通用:

var foobar = foo || default;

读取:将foobar设置为foodefault。 你甚至可以把它连锁多次:

var foobar = foo || bar || something || 42;

答案 3 :(得分:14)

稍微解释一下......

||运算符是逻辑 - or运算符。如果第一部分为真,则结果为true;如果第二部分为真,则结果为true;如果两部分均为真,则结果为true。为清楚起见,这里有一个表格:

 X | Y | X || Y 
---+---+--------
 F | F |   F    
---+---+--------
 F | T |   T    
---+---+--------
 T | F |   T    
---+---+--------
 T | T |   T    
---+---+--------

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

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

var title   = title || 'Error';

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

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

答案 4 :(得分:7)

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

之后的值

在||之后取值的值(据我记得):

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

答案 5 :(得分:7)

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

function foo(par) {
}

然后调用

foo()
foo("")
foo(null)
foo(undefined)
foo(0)

不等同。

Double pipe(||)会将第一个参数转换为boolean,如果得到的boolean为true,则执行赋值,否则将分配正确的部分。

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

假设我们有一个函数setSalary,它有一个可选参数。如果用户未提供参数,则应使用默认值10。

如果您按照以下方式进行检查:

function setSalary(dollars) {
    salary = dollars || 10
}

这会在调用时产生意外结果,如

setSalary(0) 

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

答案 6 :(得分:4)

双管操作员

这个例子有用吗?

var section = document.getElementById('special');
if(!section){
     section = document.getElementById('main');
}

也可以

var section = document.getElementById('special') || document.getElementById('main');

答案 7 :(得分:4)

虽然Cletus' answer是正确的,但我觉得应该添加更多关于"评估为false"在JavaScript中。

var title = title || 'Error';
var msg   = msg || 'Error on Request';

不仅要检查是否已提供title / msg,还要检查其中任何一个是falsy。即以下之一:

  
      
  • 假。
  •   
  • 0(零)
  •   
  • "" (空字符串)
  •   
  • 空。
  •   
  • 未定义。
  •   
  • NaN(一个特殊的数字值,意思是非数字!)
  •   

所以在行

var title = title || 'Error';

如果标题是真实的(即,不是假的,那么title =" titleMessage"等等)那么布尔OR(||)运算符找到了一个真正的' value,表示它的计算结果为true,因此它会短路并返回真值(title)。

如果标题是假的(即上面列表中的一个),那么布尔OR(||)运算符找到了一个' false'值,现在需要评估运算符的其他部分,' Error',其值为true,因此返回。

如果运营商的双方评价为假,它也会(在一些快速的firebug控制台实验之后),它会返回第二个' falsy'操作

return ("" || undefined)

返回undefined,这可能允许您在尝试将标题/消息默认为""时使用此问题中询问的行为。即在跑完之后

var foo = undefined
foo = foo || ""

foo将被设置为""

答案 8 :(得分:4)

为了向我前面的所有人说一些解释,我应该给你一些例子来理解逻辑概念。

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

答案 9 :(得分:2)

引用:“构造x = x || y是什么意思?”

指定默认值。

这意味着提供y到x 的默认值, 如果x仍在等待其值但尚未收到它或被故意省略以便回退到默认值。

答案 10 :(得分:0)

|| 是布尔OR运算符。与javascript中一样,将 undefined,null,0,false 视为 fassy 值。

它只是意味着

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"

答案 11 :(得分:-5)

我还要补充一点:这一点速记是令人厌恶的。它错误地使用了意外的解释器优化(如果第一个操作不是第二次操作则不打扰)来控制一个任务。该用途与操作员的目的无关。我不相信它应该被使用。

我更喜欢三元运算符进行初始化,例如

var title = title?title:'Error';

这为正确的目的使用单行条件操作。它仍然会玩真实的难看的游戏,但是,这是你的Javascript。