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

我正在debugging一些JavaScript,并不能解释这是什么|| 呢?

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

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

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

这是写作的简写:

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

这种布尔expression式的简写技巧在Perl中也是很常见的。 用expression式:

 a OR b 

如果abtrue则评估为true 。 所以如果a是真的,你根本不需要检查b 。 这被称为短路布尔评估,所以:

 var title = title || "Error"; 

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

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

双pipe道运算符( || )是逻辑OR运算符 。 在大多数语言中,它的工作原理如下:

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

所以它基本上是(注意,它实际上是一个伪代码,因为你必须给这个函数一个名字或者包装它()以使其工作):

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

如果你还不明白,看看这张表:

  | true false ------+--------------- true | true true false | true false 

换句话说,只有两个值都是假的,它才是错误的。

在JavaScript中它有什么不同?

JavaScript有点不同,因为它是一种松散types的语言 。 在这种情况下,这意味着你可以使用|| 运算符的值不是布尔值。 虽然没有任何意义,但是可以使用这个操作符,例如一个函数和一个对象:

 (function(){}) || {} 

那里发生了什么?

如果值不是布尔值,那么JavaScript会将隐式对话转换为布尔值 。 这意味着如果值是falsey(例如0""nullundefined (也可以参考JavaScript中的所有falsey值 )),则它将被视为false ; 否则视为true

所以上面的例子应该是true ,因为空function是真的。 那么,它不。 它返回空函数。 这是因为JavaScript的|| 操作员不像我一开始写的那样工作。 它的工作原理如下:

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

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

 function(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是假的,那么x or eitherXorY就是y 。 在这种情况下,你会得到"Either x or y is truthy." 如果y真的是真的 否则你会得到"Neither x nor y is truthy"

实际的问题

现在,当你知道如何|| 运营商的工作,你可以自己做出什么x = x || y x = x || y意思是 如果x是真的, x被分配给x ,所以实际上什么也没有发生。 否则y被分配给x 。 它通常用于定义默认参数来运行,因为默认的函数参数是在ES6中引入的,旧版浏览器不支持。 然而,它通常被认为是一个糟糕的编程习惯 ,因为它会阻止你传递一个错误的值(不一定是undefinednull )作为参数。 考虑下面的例子:

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

一见钟情看起来有效。 但是,如果你传递false作为flagA参数会发生什么(因为它是布尔值,即可以是truefalse )? 这将成为true 在这个例子中,没有办法将flagA设置为false

比较好的例子是显式检查flagA是否undefined ,如下所示:

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

虽然时间更长,但它总能正常工作,而且更容易理解(哪个OP通过问这个问题已经certificate了)。

也可以看看

  • 逻辑运营商 (MDN)
  • 提供默认值

如果没有设置标题,请使用“错误”作为默认值。

更一般的:

 var foobar = foo || default; 

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

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

多解释一下…

|| 运算符是逻辑运算符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中,如果你的variables是一个空值,它被逻辑运算符认为是错误的。 所以如果这个函数是用给定的标题调用的,那么它是一个非错误的值,因此被分配给局部variables。 但是,如果它没有被赋予一个值,那么它是一个空值,因此是错误的。 逻辑or运算符然后评估第二个expression式,并返回“错误”。 所以现在局部variables的值是'Error'。

这是因为JavaScript中的逻辑expression式的实现。 它不返回一个合适的布尔值( truefalse ),而是返回它在某些规则下给出的值,它被认为等同于true ,被认为等价于false 。 查看JavaScript引用,了解JavaScript在布尔上下文中认为是真或假的内容。

双pipe代表逻辑“或”。 当“参数未设置”时,这并不是真正的情况,因为严格地说在JavaScript中,如果你有像这样的代码:

 function foo(par) { } 

然后打电话

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

并不等同。

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

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

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

如果你这样做的检查:

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

这会给通话带来意想不到的结果

 setSalary(0) 

它仍然会按照上面描述的stream程设置10。

基本上它会检查||之前的值 评估为真,如果是的话,则取该值,否则取||之后的值。

它将采用||之后的值的值 (就目前我所记得的):

  • 未定义
  • 0
  • ''(空string或空string)

双pipe操作员

这个例子有用吗?

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

也可以

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

虽然Cletus的回答是正确的,但我觉得应该在JavaScript中对“评估为false”join更多的细节。

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

是不是只是检查是否提供标题/味精,而且如果其中任何一个是虚假的 。 即以下之一:

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

所以在行中

 var title = title || 'Error'; 

如果标题是truthy(即不是falsy,所以title =“titleMessage”等),那么布尔OR(||)运算符find了一个“true”值,这意味着它的计算结果为true,所以它短路并返回真正的价值(标题)。

如果标题是假的(即上面的列表之一),那么布尔OR(||)运算符已经find一个'假'的值,现在需要评估运算符的其他部分'Error',其值为真,并因此返回。

如果运营商的双方评估为错误,那么似乎(在一些快速的萤火虫控制台实验之后),它返回第二个“虚假”运营商。

 return ("" || undefined) 

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

 var foo = undefined foo = foo || "" 

foo将被设置为“”

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

 var name = false || "Mohsen"; # name equals to Mohsen var family = true || "Alizadeh" # family equals to true 

这意味着如果左侧被评估为真正的语句,它将被完成并且左侧将被返回并被分配给该variables。 在其他情况下,右侧将被退回并分配。

运营商有如下相反的结构。

 var name = false && "Mohsen" # name equals to false var family = true && "Alizadeh" # family equals to Alizadeh 

Quote:“什么构造x = x || y是什么意思?

指定一个默认值。

这意味着如果x仍然在等待它的值,但还没有收到它,或者为了回到默认值而被故意省略,那么给y提供一个默认的值给x

而且我还要再补充一件事情:这种简写是可憎的。 它误用了一个意外的解释器优化(不打扰第二个操作,如果第一个是真的)来控制一个任务。 这种使用与操作者的目的没有任何关系。 我不相信它应该被使用。

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

 var title = title?title:'Error'; 

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