题目
问: 变量 a 在等于什么的情况下,能是 if 语句的条件成立,控制台能输出 'OK'。
var a = ?;
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
解题思路
根据题意 == 等于操作符右边的操作数是数值。
如果只是 number 类型数值的进行比较,显然是无法满足条件的。
而 == 等于操作符在比较两个操作数时,如果两个操作数的数据类型不同,那么会先进行(强制)数据类型转换,再比较两个操作数是否相等。
那么如果 a 是一个可以转换为数值的值,就有可能使条件成立。
按照把其他数据类型的值转换成 Number 类型的 Number() 、parseInt() 和 parseFloat() 三个函数,只有 Number() 可以转换任何数据类型的值。
又按照 Number() 的转换规则,可以排除 a 是原始值类型, 因为无法让一个原始值与3个数值相等,所以只能是对象类型的值。
方案1:假设 a 是个对象
根据把对象转换为数字的规则,给 a 的 Symbol.toPrimitive 属性(方法)重新定义一个函数,可以改变其默认返回值。
具体代码如下:
var a = {
i: 0
};
// 给 a 的 Symbol.toPrimitive 属性,重新定义一个函数
a[Symbol.toPrimitive] = function toPrimitive() {
return ++this.i; // this -> a
};
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
每执行一次 == 等于比较,就会触发一次强制转换,从而会调用一次Symbol.toPrimitive 属性(方法)并返回 a.i 累加 1 的值, 所以每次强制转换的返回值都是不一样的,是累加的。
方案2:假设 a 是个数组
根据把对象转换为数字的规则,我们可以改写数组实例的 toString() 指向,具体代码如下:
var a = [1, 2, 3];
a.toString = a.shift;
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
借用数组的 shift() 方法,其功能是:删除数组的第一个元素,并返回被删除元素。
知识点
1. == 在转换操作数类型时遵循的规则
(1)如果任一操作数是布尔值,则将其转换为数值再比较是否相等。false 转换为 0,true 转换为 1。
(2)如果一个操作数是字符串,另一个操作数是数值,则尝试将字符串转换为数值,再比较是否相等。
(3)如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf() 方法取得其原始值,再根据前面的规则进行比较。
2. == 在进行比较时遵循的规则
(1)null 和 undefined 相等。
(2)null 和 undefined 不能转换为其他类型的值再进行比较。也就是说 null 和 undefined 同其他任何值都不相等。
(3)NaN 同任何值都不相等,包括它自己。
(4)如果两个操作数都是对象,则比较它们是不是同一个对象。即比较它们存储的堆内存地址是否相同。
关联笔记
以上内容,属于个人学习笔记整理,如有不对请指正。