Connaissez-vous le résultat de false&&true||true | Parlons de la priorité des opérateurs

Travailler ensemble pour créer et grandir ensemble ! C'est le 4ème jour de ma participation au "Nuggets Daily New Plan · August Update Challenge", cliquez pour voir les détails de l'événement

avant-propos

Quand je regardais le code aujourd'hui, j'ai rencontré une condition de jugement de la false && true || trueforme , et j'ai vu que je false &&croyais inconsciemment qu'il y avait une caractéristique de court-circuit , et les déclarations suivantes ont été ignorées et falsetraitées

Cependant, le résultat de l'expression ci-dessus est true!

J'ai trouvé que je ne saisissais pas complètement l'ordre des opérations d'expression, j'ai donc cet article

Cet article résout les problèmes difficiles concernant la priorité des opérateurs, explique les points sujets aux erreurs de nombreux programmeurs pour juger de l'ordre des opérations d'expression et pose quelques questions à la fin, dans l'espoir d'aider les creuseurs à saisir pleinement ce point de connaissance.

Sommaire

Sans plus tarder, montrons d' abord le tableau récapitulatif des priorités MDN .

priorité type d'opérateur associatif opérateur
19 regroupement n/a (non pertinent) ( … )
18 accès membre de gauche à droite … . …
Accès membre calculé de gauche à droite … [ … ]
new(avec liste de paramètres) n / A new … ( … )
appel de fonction de gauche à droite … ( )
Chaînage optionnel de gauche à droite ?.
17 new(pas de liste de paramètres) de droite à gauche new …
16 augmentation de poste n / A … ++
post décrémentation … --
15 NON logique (!) de droite à gauche ! …
Au niveau du bit NON (~) ~ …
Addition unaire (+) + …
Soustraction unaire (-) - …
Pré-incrémentation ++ …
Pré-décrémentation -- …
typeof typeof …
void void …
delete delete …
await await …
14 Puissance(**) de droite à gauche … ** …
13 multiplication(*) de gauche à droite … * …
division(/) … / …
reste (%) … % …
12 Ajout (+) de gauche à droite … + …
Soustraire (-) … - …
11 Décalage à gauche au niveau du bit (<<) de gauche à droite … << …
Décalage binaire vers la droite (>>) … >> …
Décalage à droite non signé (>>>) … >>> …
dix moins de (<) de gauche à droite … < …
Inférieur ou égal à (<=) … <= …
supérieur à (>) … > …
Supérieur ou égal à (>=) … >= …
in … in …
instanceof … instanceof …
9 égal (==) de gauche à droite … == …
pas égal (!=) … != …
Égalité cohérente/stricte (===) … === …
incohérent/strictement inégal (!==) … !== …
8 AND au niveau du bit (&) de gauche à droite … & …
sept XOR au niveau du bit (^) de gauche à droite … ^ …
6 OU au niveau du bit (|) de gauche à droite … | …
5 ET logique (&&) de gauche à droite … && …
4 logique ou (||) de gauche à droite … || …
Fusion nulle (??) de gauche à droite … ?? …
3 Opérateur conditionnel (ternaire) de droite à gauche … ? … : …
2 attribuer de droite à gauche … = …
… += …
… -= …
… **= …
… *= …
… /= …
… %= …
… <<= …
… >>= …
… >>>= …
… &= …
… ^= …
… |= …
… &&= …
… ||= …
… ??= …
1 virgule/séquence de gauche à droite … , …

Des difficultés

priorité

所谓优先级,就是同样一个表达式,先算那个,后算那个

最简单的例子就是加减乘除,先乘除后加减,对于这个表达式 2 + 2 * 2,相当于 2 + (2 * 2),结果为 6

我们只要在计算表达式时,按照优先级给表达式加括号,运算顺序就清晰了

由于逻辑与比逻辑或的优先级高,false && true || true 等同于 (false && true) || true,这样看起来是不是一眼就能出结果了

结合性

结合性只针对二元表达式,决定连续的同级运算符之间,要如何结合。

不太好理解,好在正儿八经的右结合性的只有

举个例子大家就明白了

  • 2 * 2 * 3 等同于 (2 * 2) * 3 结果为 12
  • 2 ** 2 ** 3 等同于 2 ** (2 ** 3) 结果为 256

new 和条件运算符并不是二元的,结合性对他们是不生效的

另一个右结合性的二元运算符是赋值,我们基本不会连续使用,因为它要求左值为变量,但还是举个例子讲一下吧,看下面这段代码:

let a = 1
a += a *= a -= 1
复制代码

运算流程是这样的

  1. 根据右结合原理,上面的表达式化为 a += (a *= (a -= 1))
  2. 展开等号, a = a + (a = a * (a = a - 1))
  3. 忽略多余的赋值运算,变量赋值, a = 1 + (1 * (1 - 1))
  4. 最后表达式结果为 1a 的值也还是 1

这里牵扯到 JS 的另一个特性:在一个表达式中,多余的赋值运算会被忽略。上面那串代码,扔到 C++ 中执行结果是 0。对此不必深究,我们在开发中是绝对用不上的

逻辑短路

拥有逻辑短路的有三个运算符:逻辑与、逻辑或、条件运算符

let num = 1
const add = () => num++
false && add()
true || add()
false ? add() : 0
true ? 0 : add()
console.log(num) // 1
复制代码

在上面这个例子中,按理来说函数调用的优先级远高于逻辑/条件运算符,但是由于逻辑短路add 一次都没有执行。

逻辑短路没有原因,是一种语言特性,你可以将其理解为懒求值:只有真正用到的时候,才进行计算表达式的值。

而上面的几句表达式的结果在函数执行前就已经确定了,函数也就没有必要执行了。

前置/后置运算符

一句话说明白,以递增运算符举例,前置递增先加后运算后置递增先运算再加

let a=1, b=1
console.log(a++) // 1
console.log(++b) // 2
复制代码

逗号运算符

逗号作为运算符时,其优先级是最低的。

有逗号分割的表达式,不管前面的结果再花哨。都以最后一段表达式的结果返回

for (let i = 0; true, false; i++) {
  console.log(i) // 一次也不会执行
}
复制代码

注意逗号作为运算符操作符的区别

console.log(1, 2, 3, 4, 5, 6) // 1 2 3 4 5 6
console.log((1, 2, 3, 4, 5, 6)) // 6
console.log([1, 2, 3]) // [1, 2, 3]
console.log([(1, 2, 3)]) // [3]
复制代码

逗号只有在表达式中作运算符使用,在其他地方都是作为操作符使用的,如:函数传参,变量声明、数组/对象定义

扩展运算符

有些掘友应该已经发现了,上面的优先级汇总表中漏了扩展运算符...,原因在于虽然我们平时叫它扩展运算符,但它其实是一种语法,只能在函数/数组/对象中使用,得到的结果是一种特殊的迭代器

我对其进行了测试,发现它的优先级低于所有运算符

let a = '123'
console.log(...a && '321') // 3 2 1
console.log(...a = '321') // 3 2 1
console.log(...a, '321') // 1 2 3 321
复制代码

最后一条语句逗号是作为操作符使用的,由于 ... 使用场景的限制,无法与逗号运算符进行比较

练习题

出几道练习题,掘友们可以尝试做一下

问题

// 第一题
let a = 1
console.log(a-- + --a)
console.log(a)

// 第二题
console.log(!2 - 1 || 0 - 2)

// 第三题
console.log(0 < 1 < 2 == 2 > 1 > 0)

// 第四题
console.log(...typeof 1)

// 第五题
var top = 1['toString'].length
var fun = new new Function()()
console.log((1 > 2 ? 1 : 2 - 10 ? 4 : 2, 1 ? top : fun))
复制代码

答案

第一题:

  • 递减运算优先于加法运算,加括号:(a--) + (--a)
  • 后置递减先运算再减,所以加号左边为 1,此时 a0
  • 前置加法先减后运算,所以加号右边为 -1,此时 a-1
  • 运算结果为 1 + -1 = 0a 最终为 -1

第二题:

  • 逻辑非优先于减法优先于逻辑或,加括号:((!2) - 1) || (0 - 2)
  • !2 转化为布尔为 false,再转化为数字为 0,式子为:(0 - 1) || (0 - 2)
  • 逻辑或前一项为 -1,为真值,触发逻辑短路,运算结果为 -1

第三题:

  • 小于/大于优先于等于,加括号:((0 < 1) < 2) == ((2 > 1) > 0)
  • 左边 true < 2true 转化为数字 1 < 2,左边结果为 true
  • 右边 true > 0true 转化为数字 1 > 0,右边结果也为 true
  • 所以,运算结果为 true

第四题:

  • typeof 1 结果为 'number'
  • 展开输出结果为 n u m b e r

第五题:

  • Notez qu'il y a une virgule au milieu de l'expression, donc ne vous souciez pas de la première moitié, regardez simplement la seconde moitié 1 ? top : fun, qui 1est la vraie valeur, donc le résultat estWindow

Dans le processus de résolution du problème, de nombreux types de conversions ont été effectués. Si vous n'êtes pas familier avec cet aspect, vous pouvez lire en détail la détection et la conversion de différents types de données dans JS.

Je ne comprends pas pourquoi la dernière question est oui, Windowjetons un coup d'œil à top === window ? À cause de la fosse rencontrée en utilisant var

En ce qui concerne l'attribut de longueur de la fonction, il y a une introduction détaillée dans l' échec de l'entretien | La longueur de la fonction

Je suppose que tu aimes

Origine juejin.im/post/7134250195641958430
conseillé
Classement