a等于什么会让下面条件成立?
var a = ?;
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
首先&&是与逻辑运算符,意思是如果每一项都为真,则整个运算结果为真,题目就变成了a等于什么的时候,a == 1 和 a == 2和 a == 3同时为真。
思路1:利用 == 的隐式转换
每次 == 都是一次隐式转换,== 在比较的时候,如果两边类型不一致,则转换为相同的数据类型。
假设a是一个对象,那么对象转化为数字类型,应该怎么转换呢?
对象转换为数字或者字符串:
- 1.查找对象的 Symbol.toPrimitive
- 2.调用对象.valueOf(),找到它 的原始值(也就是原始数据类型),js中的原始值如下:number\string\boolean\null\undefined\symbol\bigint
- 3.对象.toString() 变为字符串
- 4.字符串转换数字 Number(str)
从这个角度出发,可以通过改写a的Symbol.toPrimitive 或者valueOf()来使a的值能在==比较的时候变化。
var a = {
i: 0
};
// 或者改写valueOf / toString
a[Symbol.toPrimitive] = function () {
// this->a
return ++this.i;
};
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
//或者写成这个样子,因为有人觉得跑题,他觉得多出来了a[Symbol.toPrimitive] = function () {}这一块。
var a = {
i: 0,
[Symbol.toPrimitive]() {
return ++this.i;
}
};
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
**思路2:ES6 数据劫持 **
什么是数据劫持,数据劫持有什么用呢?
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。数据劫持是对这个属性的翻译。
我个人的理解就是:使用Object.defineProperty() 来给对象修改or添加属性。
let obj = {};
Object.defineProperty(obj, 'name', {
// 以后当我们操作对象的name属性的时候(获取或者设置),触发getter/setter
get() {
return 'hhhh';
},
//如果是obj.name,就会返回hhhh',如果是设置name属性值,那么设置的属性值就是对象的新属性值。
set(value) {
console.log(value);
}
});
那么对于这道题来说,数据劫持有什么用呢?
var a = 12; //全局上下文中,基于var/function声明变量,也相当于给window设置了属性 window.a=12
var i = 0;
Object.defineProperty(window, 'a', {
get() {
return ++i;
}
});
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
给window的a属性值添加一个函数,每次进行比较都会调用这个函数。