JavaScript(十三)操作符:布尔、相等、关系

布尔操作符

布尔操作符有 3 种:逻辑非、逻辑与和逻辑或。

逻辑非

逻辑非操作符由一个叹号(!)表示,可应用给 ECMAScript 中的任何值。它首先将操作数(任意数据类型)转换为布尔值,然后再对其取反。

它遵循如下规则:

  1. 如果操作数是对象,则返回 false。
  2. 如果操作数是空字符串,则返回 true。
  3. 如果操作数是非空字符串,则返回 false。
  4. 如果操作数是数值 0,则返回 true。
  5. 如果操作数是非 0 数值(包括 Infinity),则返回 false。
  6. 如果操作数是 null,则返回 true。
  7. 如果操作数是 NaN,则返回 true。
  8. 如果操作数是 undefined,则返回 true。

可以看下面的例子:

console.log(!false); // true
console.log(!"blue"); // false
console.log(!0); // true
console.log(!NaN); // true
console.log(!""); // true
console.log(!12345); // false
复制代码

同时使用两个叹号(!!),相当于调用了转型函数 Boolean():

console.log(!!"blue"); // true
console.log(!!0); // false
console.log(!!NaN); // false
console.log(!!""); // false
console.log(!!12345); // true
复制代码

逻辑与

逻辑与操作符由两个和号(&&)表示:

let result = true && false;
复制代码

遵循数学真值表。
如果有操作数不是布尔值,则逻辑与并不一定会返回布尔值。它遵循如下规则:

  1. 如果第一个操作数是对象,则返回第二个操作数。
  2. 如果第二个操作数是对象,则只有第一个操作数求值为 true 才会返回该对象。
  3. 如果两个操作数都是对象,则返回第二个操作数。
  4. 如果有一个操作数是 null,则返回 null。
  5. 如果有一个操作数是 NaN,则返回 NaN。
  6. 如果有一个操作数是 undefined,则返回 undefined。

逻辑与操作符是一种短路操作符,意思就是如果第一个操作数决定了结果,那么永远不会对第二个操作数求值。对逻辑与操作符来说,如果第一个操作数是 false,那么无论第二个操作数是什么值,结果也不可能等于 true。

let found = true;
let result = found && someUndeclaredVariable; // 这里会出错
console.log(result); // 不会执行这一行
复制代码

因为第一个操作数是 true,所以会返回第二个对象。而 someUndeclaredVariable 是未声明的变量,所以这里会报错。

当我们把第一个操作符改成 false:

let found = false;
let result = found && someUndeclaredVariable; // 不会出错
console.log(result); // 会执行
复制代码

因为第一个操作数是 false,所以会直接返回 false。这个时候第二个变量会被无视,所以也就不会报错。

逻辑或

逻辑或操作符由两个管道符(||)表示

let result = true || false;
复制代码

逻辑或也符合数学真值表的判定方法。

遇到有操作数不是布尔值时,遵循如下规则:

  1. 如果第一个操作数是对象,则返回第一个操作数。
  2. 如果第一个操作数求值为 false,则返回第二个操作数。
  3. 如果两个操作数都是对象,则返回第一个操作数。
  4. 如果两个操作数都是 null,则返回 null。
  5. 如果两个操作数都是 NaN,则返回 NaN。
  6. 如果两个操作数都是 undefined,则返回 undefined。

逻辑或操作符也具有短路的特性。只不过对逻辑或而言,第一个操作数求值为 true,第二个操作数就不会再被求值了。这里不再举例说明。

基于这个特性,可以避免给变量赋值 null 或 undefined。比如:

let myObject = preferredObject || backupObject;
复制代码

其中,preferredObject 变量包含首选的值,backupObject 变量包含备用的值。如果 preferredObject 不是 null,则它的值就会赋给 myObject;如果 preferredObject 是 null,则 backupObject 的值就会赋给 myObject。这种模式在 ECMAScript 代码中经常用于变量赋值。

相等操作符

ECMAScript 提供了两组相等操作符,可以按需使用。

第一组是等于和不等于,他们在比较之前执行转换。
第二组是全等和不全等,他们在比较之前不转换。

等于==和不等于!=

等于操作符用==表示,如果操作数相等则返回 true,否则返回 false。

不等于操作符用!=表示,如果操作数不相等则返回 true,否则返 false。

这两个操作符都会先进行类型转换(也叫强制类型转换)再确定操作数是否相等。

他们都遵循如下规则:

  1. 如果任一操作数是布尔值,则将其转换为数值再比较是否相等。false 转换为 0,true 转换
    为 1。

  2. 如果一个操作数是字符串,另一个操作数是数值,则尝试将字符串转换为数值,再比较是否
    相等。

  3. 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf()方法取得其原始值,再
    根据前面的规则进行比较。

在进行比较时,这两个操作符会遵循如下规则。

  1. null 和 undefined 相等。

  2. null 和 undefined 不能转换为其他类型的值再进行比较。

  3. 如果有任一操作数是 NaN,则相等操作符返回 false,不相等操作符返回 true。记住:即使两
    个操作数都是 NaN,相等操作符也返回 false,因为按照规则,NaN 不等于 NaN。

  4. 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,
    则相等操作符返回 true。否则,两者不相等。

下面是特殊情况的总结:

表达式 结果
null == undefined true
“NaN” == NaN false
5 == NaN false
NaN == NaN false
NaN != NaN true
false == 0 true
true = 1 true
true == 2 false
undefined == 0 false
null == 0 false
“5” == 5 true

全等和不全等

他们在比较相等时不转换操作数。所以他们也要判断数据类型是否相等。

另外,虽然 null == undefined 是 true(因为这两个值类似),但 null === undefined 是 false,因为它们不是相同的数据类型。

关系操作符

关系操作符包括小于(<)、大于(>)、小于等于(<=)和大于等于(>=)。

当两个变量都是数值时,按数学规则比较大小。

当有不同数据类型时,按如下规则:

  1. 如果操作数都是字符串,则逐个比较字符串中对应字符的编码。
  2. 如果有任一操作数是数值,则将另一个操作数转换为数值,执行数值比较。
  3. 如果有任一操作数是对象,则调用其 valueOf()方法,取得结果后再根据前面的规则执行比较。
  4. 如果没有 valueOf()操作符,则调用 toString()方法,取得结果后再根据前面的规则执行比较。
  5. 如果有任一操作数是布尔值,则将其转换为数值再执行比较。

在使用关系操作符比较两个字符串时,关系操作符会比较字符串中对应字符的编码。所以一般来说,“字母顺序靠后”的更大。但如果比较大小写字母,这个规则就不适用:

let result = "Brick" < "alphabet"; // true
复制代码

在这里,字符串”Brick”被认为小于字符串”alphabet”,因为字母 B 的编码是 66,字母 a 的编码是 97。所以要把他们都转成大写或小写再去比较才有意义:

let result = "Brick".toLowerCase() < "alphabet".toLowerCase(); // false
复制代码

在比较两个数值字符串也是这样:

let result = "23" < "3"; // true
复制代码

我们第一反映会觉得 23 大,但是因为是字符串,他们会比较“2”和“3”在编码里的数值。字符”2″的编码是 50,而字符”3″的编码是 51。所以后者更大。

但是如果其中一个是数值,那么另一个会先被转换成数值再比较:

let result = "23" < 3; // false
复制代码

当字符串不能转换成数值时。字符串首先会被转换为 NaN。而 NaN 和任何变量比较时都会返回 False。所以会有下面这样的神奇情况:

let result = "a" < 3; // 因为"a"会转换为NaN,所以结果是false
let result1 = NaN < 3; // false
let result2 = NaN >= 3; // false
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享