逻辑运算符&&与两个字符串在JavaScript中的运用

40
当我在两个字符串之间使用逻辑运算符 && 时,为什么会输出第二个字符串?

console.log("" && "Dog");    // ""
console.log("Cat" && "Dog"); // "Dog"

我了解到,除了0falsenullundefined""NaN之外,在像上面那样的逻辑表达式中,其他所有东西都被评估为布尔值true。但为什么输出是第二个字符串而不是第一个?为什么输出不只是“true”,因为它被评估为布尔表达式?


1
因为这就是JS的工作方式,而且像你指出的那样,真实性不仅限于布尔值。 - Dave Newton
2
请查看这个简明的答案:在最简单的术语中 - Dewey
2
请查看此答案简单来说 - Dewey
5个回答

41

在表达式中

"Cat" && "Dog"
// => "Dog"
因为你使用了&&,JavaScript会确保表达式两侧都是true。在这种情况下,"Dog"只是最后一个被评估的东西。
为了更明确,您可以这样做:
var c = "Cat" != null && "Dog" != null

虽然有点冗长,但这归结为

var c = true && true
console.log(c)
// => true

如果您想要一个布尔值的简单快捷方式,请使用 Boolean 构造函数 -

var c = Boolean("Cat" && "Dog")
console.log(c)
// => true

如果你只使用简单的REPL或JavaScript控制台,你可以非常容易地看到此输出。


根据下面的评论之一

使用||,JavaScript向您承诺至少一个方向是true。因为"Cat"为真,所以它停在那里并返回"Cat"。这被称为短路评估


"Dog" 是最后一个被评估的东西吗?那么 "Cat" || "Dog" (=> "Cat") 呢? - su-
2
@su,我在我的答案中添加了一个部分来回答你的问题 :) - Mulan
@user633183解释说,“Cat” || “Dog”在甚至没有查看||运算符之后就返回“Cat”。但我想知道,字符串“Dog”是否真的被创建了?我不确定如何检查这一点。 - Alex
Alex,“Dog”不会被评估。 - Mulan
1
那么为什么console.log("foo" && 010)的答案是8? - jay rangras
因为010 == 8。 - ahmet dundar

16

我认为这是由于逻辑运算符 && 的本质。Javascript以以下方式执行表达式 "cat" && "Dog":

检查值 "cat" - 它返回的不是 ""、0、null、undefined 或 false,而是真值(truthy)。Javascript看到了 &&,因此它继续执行表达式并遇到字符串 "Dog",它不是 ""、0、null、undefined 或 false 中的任何一个,因此也是真值(truthy),表达式结束并返回它检查的最后一个值。

如果你用 || 替换 &&,表达式将在第一个真值处结束,就像这样。

var boolean = "cat" || "dog"

返回第一个值:cat


2
+1 是的,这确实归结为逻辑运算符101,不是吗? :) 不错的写作。 - Mulan

14

@naomik的答案已经涵盖了大部分内容。如果您想深入了解,我建议查看ECMAScript规范的第11.11节:

http://www.ecma-international.org/ecma-262/5.1/#sec-11.11

在“Semantics”部分,我们可以看到:

表达式LogicalANDExpression:LogicalANDExpression&&BitwiseORExpression的结果如下所示:

  1. lref为计算LogicalANDExpression的结果。
  2. lval为GetValue(lref)的结果。
  3. 如果ToBoolean(lval)返回false,则返回lval
  4. rref为计算BitwiseORExpression的结果。
  5. 返回GetValue(rref)的结果。

这个问题已经有3年了,为什么要发表另一个答案? - Scott
14
因为我刚找到这个问题,并且认为自己有一些额外的知识可以分享,之前没有人分享过它;)我认为在SO上问题没有“过期日期”:) - José Ernesto Lara Rodríguez
嗨,lref、lval、rref、rval的完整形式是什么? - firstpostcommenter
@firstpostcommenter 这些变量在引用中已经定义:lref 是 LogicalANDExpression(即左侧项)求值的结果,lval 是 GetValue(lref) 的结果,以此类推。关于 GetValue 的定义,建议查看链接文档。 - José Ernesto Lara Rodríguez

0

由于逻辑运算的特性,如果你需要测试两个条件是否都成立,而你已经知道第一个条件成立,那么整个测试的结果完全依赖于第二个条件。

true && someValue 等价于 someValue

因此,运算符 && 可以通过返回它的操作数而不是 true/false 值来处理,只需测试第一个操作数而不是第二个操作数。

a && b:

  • 如果 a 的值为 false,则无需继续测试,直接返回 a(因为它是 false)

  • 否则,如果 a 的值为 true,则结果完全取决于 b,所以只需返回 b(无需测试 b 的值为 true 还是 false,直接返回即可)

代码中的实现如下:

function and(a,b) {
    if(!a) return a;
    return b;
}

同样,运算符||可以被定义为

function or(a,b) {
    if(a) return a;
    return b;
}

返回操作数而不是true/false有一些优点:

  • 需要较少的评估(请注意,在两种情况下都不会评估b)

  • 不需要定义true/false,因此可以更广泛地使用,甚至跨语言或如果“true”的值更改

  • 可以“黑客”使用,无需if,做像string1 && string2这样有用的含义:“如果string1不为空,则使用string2,否则保持为空(用文本“word”替换字符串的每个单词:aString.split(" ").map(function(word) {return word && "word"});

JavaScript程序员喜欢这种东西(利用一个运算符的副作用来获得不同的、意想不到的行为),他们这样做是为了在聚会上展示语言知识。:D


0

你可以更简单地实现:

为了验证字符串是否为空,你也可以在Javascript中使用!运算符。

let a = '';
console.log(!a);  // => true

a = 'foo';
console.log(!a)   // => false

如果您再次使用此操作符,现在您将否定一个布尔值而不是一个字符串。在您的情况下:
console.log(!!'' && !!'Dog');    // => false
console.log(!!'Cat' && !!'Dog'); // => true

你也可以看看这篇文章:JavaScript 中的双重否定(!!)有什么用途?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接