( | ) 和 ( || ) 有什么区别?

24

|||在Javascript中有什么区别?

此外,&&&有什么区别?


4
需要注意的是,这不仅适用于JavaScript。几乎每种编程语言都使用相同的运算符执行相同的功能。 - Brian Roach
1
@Brian Roach:非常抱歉!! - Buffon
不需要,我只是提一下而已。 - Brian Roach
@BrianRoach - 实际上,JavaScript的||&&与(许多)其他编程语言不同,因为它们返回一个操作数的值而不是布尔值(当然,除非操作数本身是布尔值)。 - nnnnnn
@nnnnnn - 它们的区别不在于它们如何“不同”于 |&。双重操作是逻辑操作,单一操作是位运算。JS 中逻辑运算的返回值并不是问题的一部分。此外,在 if 语句中使用时,只有当它等于 0 时,该值才为 false。所有其他条件都被视为“true”。它返回值的事实仅仅是一个副作用,并被丢弃。例如,在 Java 中,逻辑 &&|| 运算符仅接受布尔参数;这并不影响 &&|| 是逻辑运算符,而 &| 是位运算符的事实。 - Brian Roach
@BrianRoach - 没错,在一般情况下,位运算与非位运算是主要区别。如果在 if 语句中使用,返回 true 和返回真值的区别并不重要。但问题并没有提及 if 语句,也没有说明操作数的类型。因此,考虑到这个问题被标记为“JavaScript”,逻辑运算符的工作方式确实很重要,运算符返回的类型也很重要。 - nnnnnn
7个回答

26

| 是按位或运算符,|| 是逻辑或运算符。

按位或运算符会将两个数字逐位进行比较,并生成一个新的整数,其中包含两个输入中的所有1。因此,0101 | 1010 将产生 1111

逻辑或运算符 || 检查值的“真实性”(根据类型而定,对于整数来说,0为假,非零为真)。它从左到右评估每个语句,并返回第一个真实值。因此,0101 || 1010 将返回 0101,它是真实的,因此整个语句被认为是真实的。

相同的逻辑也适用于 &&&0101 & 1010 = 0000。然而,0101 && 1010 求值为 1010&& 返回最后一个真实值,只要两个操作数都是真实的)。


5
确实有疑问。除非是用于位运算,否则不要使用按位“或”运算符。 - Chris Eberle
3
然而,逻辑运算符 || 只检查两个输入的真值。因此,0101 || 1010 的结果将会是真(true)是错误的。首先, || 使用短路求值(short-circuit evaluation),如果第一个操作数为"真(truthy)",则不会评估第二个操作数。其次, || 不返回 truefalse,它返回第一个操作数的值(如果是真值),否则返回第二个操作数的值。因此, 0101 || 1010 返回 0101(或者65,由于数字字面量中的前导0表示八进制)。'A' || 'B' 返回 'A' - nnnnnn
@nnnnnn 非常有趣。我知道短路的概念,但我没想到它会返回第一个真值。那么 && 如何处理真值(因为它并没有实现短路)? - Chris Eberle
&& 运算符也使用短路求值:如果第一个操作数为“假”,则返回该操作数,不会计算第二个操作数;否则返回第二个操作数。 - nnnnnn
@SiPlus,你有没有看评论历史,还是直接跳进来的?你是错误的。 - Chris Eberle
显示剩余2条评论

13

不同之处在于逻辑运算符仅考虑每个输入的表面价值,将它们作为整体处理,而按位运算符在位级别上工作:

var thetruth = false;
var therest = true;

var theuniverse = thetruth && therest; //false
var theparallel = thetruth && thetruth; //true

var theindifferent = thetruth || therest; //true
var theideal = thetruth || thetruth; // false

var thematrix = 5346908590;
var mrsmith = 2354656767;

var theoracle = thematrix & mrsmith; //202445230
var theone = thematrix | mrsmith; //7499120127

我知道,但是... while(a&&b)while(a&b) 有什么区别? - Buffon
2
@Buffon 对于任何非数字类型,后者都会返回false。 - Raynos

4
另一个区别在于 || 使用短路求值。也就是说,只有在左侧为 false(或在布尔上下文中转换为 false,例如 0""null 等)时,才会评估右侧。同样的,只有左侧为 true(或非零、非空字符串、对象等)时,&& 才会评估右侧。因为 |& 的结果取决于每个值中的确切位,所以它们总是评估两个侧。
这样设计的原因是,对于 ||,如果任何一侧为 true,则整个表达式都为 true,因此没有必要进一步评估。 && 也是相同的,但是反过来。
对于 || 的精确逻辑是,如果左侧是“truthy”,则返回该值(注意它没有转换为布尔值),否则评估并返回右侧。对于 &&,如果左侧是“falsey”,则返回它,否则评估并返回右侧。
以下是一些示例:
false && console.log("Nothing happens here");
true || console.log("Or here");
false || console.log("This DOES get logged");
"foo" && console.log("So does this");

if (obj && obj.property) // make sure obj is not null before accessing a property

+1。这是对||运算符目前唯一正确的解释。其他人没有提到短路求值,也没有提到该运算符返回第一个或第二个操作数的实际值,而不是布尔值。 - nnnnnn

1
从JavaScript的角度来看,它还有更多的内容。
var a = 42;
var b = "abc";
var c = null;

a || b;     // 42
a && b;     // "abc"

c || b;     // "abc"
c && b;     // null

|| 和 && 运算符都对第一个操作数(a 或 c)执行布尔测试。如果操作数不是布尔值(在这里不是),则会发生正常的 ToBoolean 强制转换,以便进行测试。

对于 || 运算符,如果测试为 true,则 || 表达式的结果为第一个操作数的值(a 或 c)。如果测试为 false,则 || 表达式的结果为第二个操作数的值(b)。

相反,对于 && 运算符,如果测试为 true,则 && 表达式的结果为第二个操作数的值(b)。如果测试为 false,则 && 表达式的结果为第一个操作数的值(a 或 c)。

|| 或 && 表达式的结果始终是其中一个操作数的基础值,而不是测试的(可能强制转换的)结果。在 c && b 中,c 为 null,因此为假值。但是 && 表达式本身的结果为 null(c 中的值),而不是测试中使用的强制转换的 false。


1
稍微通俗地解释一下: &&|| 是逻辑运算符。这意味着它们用于逻辑比较;
if (a == 4 && b == 5)

这意味着 "如果a等于四且b等于五"
"|"和"&"是按位运算符。它们以特定的方式操作位,维基文章详细解释了它们的工作原理。

http://en.wikipedia.org/wiki/Bitwise_operation


1

单竖线 | 是按位或运算符。 如果你执行 2 | 3,它会将其转换为二进制并执行或操作。 01 11 结果是11,等于3。

而 || 运算符检查第一个参数是否为真,如果为真则返回该值,否则继续执行其他运算符。 2 || 3 返回2,因为2为真。


0

我想要补充的一点是,|| 运算符用于在所分配的值未定义时分配默认值。例如,你将一个对象分配给某个名为 test 的对象,如果你不希望 test 未定义,则可以执行以下操作以确保 test 的值不会未定义。

var test = obj || {};

因此,如果 obj 未定义,则 test 的值将为空对象。

所以它也被用于为对象分配默认值。


我认为你所说的“所以如果obj未定义,那么test的值将为空对象”是指未定义或空值。 - thread-game

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