一、题目描述
// 下述代码会在什么情况下打印1?
var a = ?;
if (a == 1 && a == 2 && a == 3) {
console.log(1);
}
二、考察知识点
1、隐式转换
2、对象与原始数据类型比较的过程及底层原理
三、方案一
1、代码
var a = [1, 2, 3];
a.join = a.shift;
if (a == 1 && a == 2 && a == 3) {
console.log(1);
}
2、分析
- 数组也是一种对象
- 数组调用toString方法时,会对其中每一个元素调用toString方法并返回结果,而后调用join方法将结果拼接为字符串
- 数组的shift方法,会每次删除数组中的第一个元素(改变原数组),返回值是被删除的元素
- 将a.join方法改写为a.shift方法,这样数组在调用toString方法时调用的join方法就变成了shift方法,每次返回第一个元素,并且正好删除第一个元素,那么if判断就成立了
var a = [1, 2, 3];
// 对a调用toSting方法 底层操作为:
var aStr = [a[0].toString(), a[1].toString(), a[2].toString()].join();
console.log(aStr);
// 将a.join方法修改为a.shift,相当于:
var aStr1 = [a[0].toString(), a[1].toString(), a[2].toString()].shift();
console.log(aStr1); // 返回值为1
// 每次 去调用 shift 就会改变一次原数组
a.join = a.shift;
// if判断条件做从往右执行
// 指行到 a==1 shift调用第一次,返回1
// 指行到 a==2 shift调用第二次,返回2
// 指行到 a==3 shift调用第二次,返回3
// 满足条件
if (a == 1 && a == 2 && a == 3) {
console.log(1);
}
四、方案二
1、代码
var a = {
i: 1,
toString: function () {
return a.i++;
}
}
if (a == 1 && a == 2 && a == 3) {
console.log(1);
}
2、分析
- 对象在转换为原始类型时,会先调用对象的valueOf方法,随后调用toString方法
- 此方案就是直接通过为a提供一个toString方法来实现每次调用返回不同的值