细说 JS 比较关系

83 阅读2分钟

比较关系

比较符

  • ==(相等) 比较两个操作数的值是否相等。
  • !=(不想等) 比较两个操作数的值是否不相等。
  • ===(全等) 比较两个操作数的值是否相等,同时检测它们的类型是否相同。
  • !==(不全等) 比较两个操作数的值是否不相等,同时检测它们的类型是否不相同。

宽松相对(==)和严格相等(===)

  • ==允许在相等比较中进行强制类型转换,===却不允许。
  • null == undefined比较相等,其中隐式强制类型转换利用 ToPrimitive(抽象操作)的所有特性。
  • 两边的值中有 true 或 false,最好不使用==。
  • 两边的值中有[]、""或 0,尽量不要使用==。

ToPrimitive(抽象操作)

js 中,将对象转换成原始值时,会调用 toPrimitive()内部函数。

  • 首先检查该值是否有 valueOf() 方法。如果有并且返回基本类型值,使用该值进行强制类型转换。
  • 没有就使用 toString() 的返回值来进行强制类型转换。
  • 如果 valueOf() 和 toString() 均不返回基本类型值,会产生 TypeError 错误。
const testObj = { value: 123 };
testObj.valueOf = function () {
    console.log('get value');
    return this.value;
};
console.log(testObj == 123); // true

const testArr = [1, 2, 3];
testArr.valueOf = null;
console.log(testObj == '1,2,3'); // true

const testData = [1, 2, 3];
testData.valueOf = function () {
    return new String('1,2,3');
};
testData.toString = function () {
    return new String('1,2,3');
};
console.log(testData == '1,2,3'); // TypeError

抽象比较关系

a > b,双方首先调用 ToPrimitive,如果结果出现非字符串,根据 Number 规则双方强制转换为数字类型。

// JS中 <= 是不大于的意思
const a = { b: 24 };
const b = { b: 35 };

// [object object]
a < b; // false
a > b; // false
a == b; // false

// 等于 !(a < b)
a <= b; // true

// 等于 !(a > b)
a >= b; // true

无关紧要的小知识

为什么有时用void 0代替undefined?

  • undefinedES5中已经是全局对象的一个只读(read-only)属性了,它不能被重写。但是在局部作用域中,还是可以被重写的。
  • void运算符能对给定的表达式进行求值,然后返回undefined。即void后面你随便跟上一个表达式,返回的都是undefined,如 void (2), void (‘hello’)。
  • void是不能被重写的,但为什么是void 0呢,因为void 0是表达式中最短的。