前端JavaScript基础训练系列一百二十八:短路运算

本文详细解释了JavaScript中的短路运算符(&&,||)的短路特性,以及它们在条件判断中的执行顺序,包括与三元运算符(?)的关联性。此外,还讨论了运算符的优先级和组合顺序对代码执行的影响。
摘要由CSDN通过智能技术生成

附注栏提到过 && 和 || 运算符的“短路”(short circuiting)特性。下面我们将
对此进行详细介绍。
对 && 和 || 来说,如果从左边的操作数能够得出结果,就可以忽略右边的操作数。我们将 这种现象称为“短路”(即执行最短路径)。
以a && b为例,如果a是一个假值,足以决定&&的结果,就没有必要再判断b的值。同 样对于 a || b,如果 a 是一个真值,也足以决定 || 的结果,也就没有必要再判断 b 的值。
“短路”很方便,也很常用,如:

     function doSomething(opts) {
          if (opts && opts.cool) {
// .. }
}

opts && opts.cool中的opts条件判断如同一道安全保护,因为如果opts未赋值(或者 不是一个对象),表达式 opts.cool 会出错。通过使用短路特性,opts 条件判断未通过时 opts.cool 就不会执行,也就不会产生错误!
|| 运算符也一样:

     function doSomething(opts) {
          if (opts.cache || primeCache()) {
// .. }
}

这里首先判断 opts.cache 是否存在,如果是则无需调用 primeCache() 函数,这样可以避
免执行不必要的代码。

更强的绑定

回顾一下前面多个运算符串联在一起的例子:

     a && b || c ? c || b ? a : c && b : a

其中 ? : 运算符的优先级比 && 和 || 高还是低呢?执行顺序是这样? a && b || (c ? c || (b ? a : c) && b : a)
还是这样?

     (a && b || c) ? (c || b) ? a : (c && b) : a

答案是后者。因为 && 运算符的优先级高于 ||,而 || 的优先级又高于 ? :。
因此表达式(a && b || c)先于包含它的? :运算符执行。另一种说法是&&和||比? :的 绑定更强。反过来,如果 c ? c… 的绑定更强,执行顺序就会变成 a && b || (c ? c…)。

关联

&&和||运算符先于? :执行,那么如果多个相同优先级的运算符同时出现,又该如何处
理呢?它们的执行顺序是从左到右还是从右到左? 一般说来,运算符的关联(associativity)不是从左到右就是从右到左,这取决于组合
(grouping)是从左开始还是从右开始。
请注意:关联和执行顺序不是一回事。 但它为什么又和执行顺序相关呢?原因是表达式可能会产生副作用,比如函数调用:

var a = foo() && bar();

这里 foo() 首先执行,它的返回结果决定了 bar() 是否执行。所以如果 bar() 在 foo() 之
前执行,整个结果会完全不同。
这里遵循从左到右的顺序(JavaScript 的默认执行顺序),与 && 的关联无关。因为上例中只
有一个 && 运算符,所以不涉及组合和关联。
而a && b && c这样的表达式就涉及组合(隐式),这意味着a && b或b && c会先执行。
从技术角度来说,因为&&运算符是左关联(||也是),所以a && b && c会被处理为(a && b) && c。不过右关联 a && (b && c) 的结果也一样。
如果&&是右关联的话会被处理为a && (b && c)。但这并不意味着c会在b 之前执行。右关联不是指从右往左执行,而是指从右往左组合。任何时候, 不论是组合还是关联,严格的执行顺序都应该是从左到右,a,b,然后 c。
所以,&& 和 || 运算符是不是左关联这个问题本身并不重要,只要对此有一个准确的定义

即可。 但情况并非总是这样。一些运算符在左关联和右关联时的表现截然不同。 比如 ? :(即三元运算符或者条件运算符):

a ? b : c ? d : e;
? : 是右关联,它的组合顺序是以下哪一种呢?
• a ? b : (c ? d : e)
 (a ? b : c) ? d : e

答案是a ? b : (c ? d : e)。和&&以及||运算符不同,右关联在这里会影响返回结果, 因为 (a ? b : c) ? d : e 对有些值(并非所有值)的处理方式会有所不同。
举个例子:

    true ? false : true ? true : true;
     true ? false : (true ? true : true);
     (true ? false : true) ? true : true;
// false
// false
// true

在某些情况下,返回的结果没有区别,但其中却有十分微妙的差别。例如:

true ? false : true ? true : false;
true ? false : (true ? true : false);
(true ? false : true) ? true : false;
// false
// false
// false

这里返回的结果一样,运算符组合看似没起什么作用。然而实际情况是:

var a = true, b = false, c = true, d = true, e = false; a ? b : (c ? d : e); // false, 执行 a 和 b
(a ? b : c) ? d : e; // false, 执行 a, b 和 e

这里我们可以看出,? : 是右关联,并且它的组合方式会影响返回结果。 另一个右关联(组合)的例子是 = 运算符。本章前面介绍过一个串联赋值的例子:

    var a, b, c;
     a = b = c = 42;

它首先执行 c = 42,然后是 b = …,最后是 a = …。因为是右关联,所以它实际上是这样 来处理的:a = (b = (c = 42))。

  • 22
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值