抽象相等操作符 ("loose equality","double equals") ,即 == ,相信大家伙儿都不陌生,我们都知道它比较的两个操作数如果是不同类型的,就会尝试在比较之前将它们转换为相同类型(原始值)。
比如:如果操作数之一是对象,另一个是数字或字符串,会尝试使用对象的 valueOf() ,若无法转换成原始值,再调用对象的 toString() 方法将对象转换为原始值。
举个例子:
// 阿里、百度、腾讯面试题
// ? 位置应该怎么写才能输出 true
var a = ?;
console.log(
a == 1 &&
a == 2 &&
a == 3
);
分析:这道题是在考抽象相等操作符(==)的运算规则以及类型转换的规则,那么我们开始尝试一下。
先贴一下 == 操作符的判断规则:
- 如果两个操作数都是对象,则仅当两个操作数都引用同一个对象时才返回 true。
- 如果一个操作数是 null,另一个操作数是 undefined,则返回 true。
- 如果两个操作数是不同类型的,就会尝试在比较之前将它们转换为相同类型:
-
- 当数字与字符串进行比较时,会尝试将字符串转换为数字值。
- 如果操作数之一是 Boolean,则将布尔操作数转换为1或0。
-
- 如果是 true,则转换为 1。
- 如果是 false,则转换为 0。
- 如果操作数之一是对象,另一个是数字或字符串,会尝试使用对象的 valueOf() 和 toString() 方法将对象转换为原始值。
- 如果操作数具有相同的类型,则将它们进行如下比较:
- String:true 仅当两个操作数具有相同顺序的相同字符时才返回。
- Number:true 仅当两个操作数具有相同的值时才返回。+0 并被 -0 视为相同的值。如果任一操作数为NaN,则返回 false。
- Boolean:true 仅当操作数为两个 true 或两个 false 时才返回 true。
(1)、a 等于 1 或 2 或 3,显然都不行;
(2)、a 如果是 Boolean 值,只能转换成 0 或 1;
(3)、那 a 应该是一个对象,另一个值是数字,那就符合这一条判断规则:如果两个操作数是不同类型的,并且操作数之一是对象,另一个是数字或字符串,会尝试使用对象的 valueOf() 和 toString() 方法将对象转换为原始值。
var a = {}
console.log(a.valueOf()) // {}
console.log(a.toString()) // "[object Object]"
// 在这里你会发现 a 对象的 valueOf() 和 toString() 方法都不能转换成原始值,
// 那我们就重写 a 对象的 valueOf() 或 toString() 方法,让它返回原始值。
var a = {
valueOf: function() {
return 1;
}
};
// 但因为是被比较了3次,所以应该 this.value++
var a = {
value: 1,
valueOf: function() {
return this.value++;
}
};
console.log(
a == 1 &&
a == 2 &&
a == 3
); // true