382

鉴于这段 JavaScript...

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';

var f = a || b || c || d || e;

alert(f); // 4

有人可以向我解释一下这种技术叫什么(我最好的猜测是这个问题的标题!)?以及它是如何/为什么起作用的?

我的理解是,变量f将被分配为第一个变量的最接近的值(从左到右),该变量的值不是空值或未定义,但我没有设法找到关于这种技术的很多参考资料并且有看到它用了很多。

另外,这种技术是 JavaScript 特有的吗?我知道在 PHP 中做类似的事情会产生f一个真正的布尔值,而不是d它本身的值。

4

12 回答 12

240

有关说明,请参见短路评估。这是实现这些运算符的常用方法;它不是 JavaScript 独有的。

于 2010-01-20T10:54:26.753 回答
226

这是为了分配一个默认值,在这种情况下是 的值y,如果x变量是的。

JavaScript 中的布尔运算符可以返回一个操作数,而不像其他语言那样总是返回一个布尔结果。

逻辑 OR 运算符 ( ||) 返回其第二个操作数的值,如果第一个操作数为假,否则返回第一个操作数的值。

例如:

"foo" || "bar"; // returns "foo"
false || "bar"; // returns "bar"

Falsy值是false在布尔上下文中使用时强制转换的值,它们是0, null, undefined, 一个空字符串,NaN当然还有false.

于 2010-06-21T20:11:51.397 回答
214

Javacript逻辑运算符||&&. 但是,它与其他语言的不同之处在于它返回停止执行的最后一个值的结果,而不是 atruefalse值。

以下值在 JavaScript 中被认为是虚假的。

  • 错误的
  • 空值
  • ""(空字符串)
  • 0
  • 不明确的

忽略运算符优先级规则并保持简单,以下示例显示了哪个值停止了评估,并作为结果返回。

false || null || "" || 0 || NaN || "Hello" || undefined // "Hello"

前 5 个值NaN是假的,所以它们都是从左到右计算的,直到它满足第一个真值 -"Hello"这使得整个表达式为真,所以任何进一步的东西都不会被计算,并"Hello"作为表达式的结果返回. 同样,在这种情况下:

1 && [] && {} && true && "World" && null && 2010 // null

前 5 个值都是真值并被求值,直到它满足null使表达式为假的第一个假值 ( ),因此2010不再求值,并null作为表达式的结果返回。

您给出的示例是利用 JavaScript 的这个属性来执行赋值。它可以用于需要在一组值中获取第一个真值或假值的任何地方。下面的代码会将值分配给"Hello"b因为它可以更容易地分配默认值,而不是进行 if-else 检查。

var a = false;
var b = a || "Hello";

您可以将下面的示例称为对该功能的利用,我相信它会使代码更难阅读。

var messages = 0;
var newMessagesText = "You have " + messages + " messages.";
var noNewMessagesText = "Sorry, you have no new messages.";
alert((messages && newMessagesText) || noNewMessagesText);

在警报内部,我们检查是否messages为假,如果是,则评估并返回noNewMessagesText,否则评估并返回newMessagesText。由于在这个例子中它是假的,我们在 noNewMessagesText 和 alert 处停下来"Sorry, you have no new messages."

于 2010-06-21T21:02:19.060 回答
52

Javascript 变量没有类型,因此 f 可以分配一个整数值,即使它是通过布尔运算符分配的。

f 被分配了不等于 false的最接近的值。所以 0, false, null, undefined, 都被传递过来了:

alert(null || undefined || false || '' || 0 || 4 || 'bar'); // alerts '4'
于 2010-01-20T10:58:00.913 回答
32

它没有任何魔法。布尔表达式 likea || b || c || d是惰性求值的。Interpeter 寻找 的值a,它是未定义的,所以它是假的,所以它继续前进,然后它看到b哪个为空,它仍然给出错误的结果,所以它继续前进,然后它看到c- 同样的故事。最后它看到d并说'嗯,它不是空的,所以我有我的结果'并将它分配给最终变量。

这个技巧适用于所有对布尔表达式进行惰性短路评估的动态语言。在静态语言中它不会编译(类型错误)。在渴望评估布尔表达式的语言中,它会返回逻辑值(即在这种情况下为真)。

于 2010-01-20T10:58:21.287 回答
10

这个问题已经得到了几个很好的答案。

总之,这种技术利用了语言编译方式的一个特性。也就是说,JavaScript 会“短路”布尔运算符的求值,并将返回与第一个非 false 变量值或最后一个变量包含的任何值相关联的值。请参阅 Anurag 对那些将评估为假的值的解释。

由于几个原因,使用这种技术不是很好的做法;然而。

  1. 代码可读性:这是使用布尔运算符,如果不理解此编译方式的行为,则预期结果将是布尔值。

  2. 稳定性:这是使用一种语言编译方式的特性,该特性在多种语言之间是不一致的,因此,它可能会成为未来更改的目标。

  3. 记录的功能:有一个现有的替代方案可以满足此需求并且在更多语言中保持一致。这将是三元运算符:

    () ? 值 1:值 2。

使用三元运算符确实需要更多的输入,但它清楚地区分了正在评估的布尔表达式和正在分配的值。此外,它可以被链接起来,因此可以重新创建上面执行的默认分配类型。

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';

var f =  ( a ) ? a : 
                ( b ) ? b :
                       ( c ) ? c :
                              ( d ) ? d :
                                      e;

alert(f); // 4
于 2016-06-03T14:19:53.217 回答
8

返回输出第一个真值

如果全部为假,则返回最后一个假值。

例子:-

  null || undefined || false || 0 || 'apple'  // Return apple
于 2016-03-15T12:20:02.310 回答
4

它将新z变量(这是在不存在的情况下提供默认值的一种相对常见的方式。xyx

例如,如果你有一个带有可选回调参数的函数,你可以提供一个不做任何事情的默认回调:

function doSomething(data, callback) {
    callback = callback || function() {};
    // do stuff with data
    callback(); // callback will always exist
}
于 2010-06-21T20:13:32.873 回答
3

它被称为短路算子。

短路评估说,只有当第一个参数不足以确定表达式的值时,才会执行或评估第二个参数。当 OR (||) 函数的第一个参数计算结果为 true 时,整体值必须为 true。

它也可以用来设置函数参数的默认值。`

function theSameOldFoo(name){ 
  name = name || 'Bar' ;
  console.log("My best friend's name is " + name);
}
theSameOldFoo();  // My best friend's name is Bar
theSameOldFoo('Bhaskar');  // My best friend's name is Bhaskar`
于 2017-12-22T11:17:19.483 回答
2

这意味着如果x设置了,则值为zx否则如果y设置了,则其值将设置为z的值。

if(x)
  z = x;
else
  z = y;

这是可能的,因为 JavaScript 中的逻辑运算符不返回布尔值,而是返回完成操作所需的最后一个元素的值(在 OR 语句中,它将是第一个非假值,在 AND 语句中,它将是最后一个)。如果操作失败,则false返回。

于 2010-06-21T20:11:40.847 回答
1

它将评估 X,如果 X 不为空,则为空字符串或 0(逻辑假),然后将其分配给 z。如果 X 为 null、空字符串或 0(逻辑假),则它将 y 分配给 z。

var x = '';
var y = 'bob';
var z = x || y;
alert(z);

将输出'bob';

于 2010-06-21T20:13:16.807 回答
1

根据比尔·希金斯的博客文章;Javascript 逻辑 OR 赋值习语(2007 年 2 月),这种行为从 v1.2 开始是正确的(至少)

他还建议了它的另一种用途(引用):“跨浏览器差异的轻量级标准化

// determine upon which element a Javascript event (e) occurred
var target = /*w3c*/ e.target || /*IE*/ e.srcElement;
于 2012-12-21T18:14:25.587 回答