我正在调试一些JavaScript,无法解释这个||做什么:
function (title, msg) {
var title = title || 'Error';
var msg = msg || 'Error on Request';
}
为什么这个家伙使用var title = title || 'ERROR'?我有时也看到它没有var声明。
我正在调试一些JavaScript,无法解释这个||做什么:
function (title, msg) {
var title = title || 'Error';
var msg = msg || 'Error on Request';
}
为什么这个家伙使用var title = title || 'ERROR'?我有时也看到它没有var声明。
当前回答
这意味着title参数是可选的。因此,如果你不带参数调用该方法,它将使用默认值“Error”。
它是写作的简写:
if (!title) {
title = "Error";
}
这种使用布尔表达式的简写技巧在Perl中也很常见。用这样的表达式:
a OR b
如果a或b为真,它的值为真。所以如果a为真,你根本不需要检查b。这被称为短路布尔计算,因此:
var title = title || "Error";
基本上检查title的结果是否为false。如果是,则返回"Error",否则返回title。
其他回答
什么是双管运算符(||)?
双管道操作符(||)是逻辑或操作符。在大多数语言中,它是这样工作的:
如果第一个值为false,则检查第二个值。如果这个值为真,它就返回真,如果第二个值为假,它就返回假。 如果第一个值为真,它总是返回真,不管第二个值是什么。
它的工作原理是这样的:
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将隐式转换为布尔值。这意味着如果值是假的(例如0,"",null, undefined(参见JavaScript中的所有假值)),它将被视为假的;否则它就被当作真的。
所以上面的例子应该给出true,因为空函数是true。其实并不是这样。它返回空函数。这是因为JavaScript的||操作符不能像我开头写的那样工作。它的工作原理如下:
如果第一个值为假值,则返回第二个值。 如果第一个值为真值,则返回第一个值。
惊讶吗?实际上,它与传统的||操作符“兼容”。它可以写成如下函数:
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*/));
你会得到" x或y是对的"
如果x是假的,要么xory是y,在这种情况下,你会得到"要么x要么y是真的"如果y是真的;否则你就会得到" x和y都不是真理"
真正的问题
现在,当你知道||算子是如何工作的,你可能自己就能知道x = x || y是什么意思。如果x为真,x被赋值给x,所以实际上什么都不会发生;否则y赋值给x。通常用于定义函数中的默认形参。然而,它通常被认为是一种糟糕的编程实践,因为它阻止您将错误的值(不一定是未定义或null)作为参数传递。考虑下面的例子:
function badFunction(/* boolean */flagA) {
flagA = flagA || true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
乍一看,它是有效的。然而,如果你传递false作为flagA参数会发生什么(因为它是布尔值,即可以为真或假)?这将成为现实。在这个例子中,没有办法将flagA设置为false。
更好的方法是显式检查flagA是否未定义,如下所示:
function goodFunction(/* boolean */flagA) {
flagA = typeof flagA !== "undefined" ? flagA : true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
虽然它更长,但它总是有效的,而且更容易理解。
您还可以使用ES6语法作为默认函数参数,但请注意,它不适用于老式浏览器(如IE)。如果您希望支持这些浏览器,您应该使用Babel编译您的代码。
请参见MDN上的逻辑运算符。
这意味着title参数是可选的。因此,如果你不带参数调用该方法,它将使用默认值“Error”。
它是写作的简写:
if (!title) {
title = "Error";
}
这种使用布尔表达式的简写技巧在Perl中也很常见。用这样的表达式:
a OR b
如果a或b为真,它的值为真。所以如果a为真,你根本不需要检查b。这被称为短路布尔计算,因此:
var title = title || "Error";
基本上检查title的结果是否为false。如果是,则返回"Error",否则返回title。
虽然Cletus的回答是正确的,但我觉得应该在JavaScript中添加更多关于“评估为假”的细节。
var title = title || 'Error';
var msg = msg || 'Error on Request';
不仅仅是检查是否提供了title/msg,而且还检查它们中的任何一个是假的。即下列其中一项:
假的。 0(零) ""(空字符串) null。 未定义的。 NaN(一个特殊的数字值,意思不是一个数字!)
在这一行中
var title = title || 'Error';
如果title为真(即,不是假的,所以title = "titleMessage"等),那么布尔OR(||)运算符已经找到了一个“真”值,这意味着它的计算结果为真,因此它短路并返回真值(title)。
如果title是假的(即上面的列表之一),那么布尔OR(||)运算符已经找到了一个“假”值,现在需要计算运算符的另一部分“Error”,该运算符的计算结果为真,因此返回。
如果运算符两边的值都为false,它也会返回第二个“falsy”运算符(经过一些快速的firebug控制台实验)。
i.e.
return ("" || undefined)
返回undefined,这可能是为了允许您在尝试将title/message默认为""时使用此问题中询问的行为。也就是跑步之后
var foo = undefined
foo = foo || ""
Foo将被设置为""
双管代表逻辑上的“或”。这不是真正的情况下,“参数未设置”,因为严格在JavaScript中,如果你有这样的代码:
function foo(par) {
}
然后调用
foo()
foo("")
foo(null)
foo(undefined)
foo(0)
不相等。
双管道(||)将把第一个参数强制转换为布尔值,如果结果布尔值为真-执行赋值,否则它将赋值正确的部分。
如果你检查未设置参数,这很重要。
我们有一个函数setSalary,它有一个可选参数。如果用户没有提供参数,则应该使用默认值10。
如果你这样检查:
function setSalary(dollars) {
salary = dollars || 10
}
这将为调用提供一个意想不到的结果,例如:
setSalary(0)
它仍然会按照上面描述的流程设置10。
我还要补充一点:这种简写令人厌恶。它误用了一个意外的解释器优化(如果第一个操作为真,就不麻烦第二个操作)来控制赋值。这种用法与操作符的目的无关。我不认为它应该被使用。
我更喜欢用三元运算符来初始化,例如,
var title = title?title:'Error';
这使用一行条件操作来达到正确的目的。它仍然与真实玩难看的游戏,但这是JavaScript为你。