隐式转换规则
JavaScript中,当涉及到加运算或==判断时,会触发隐式转换规则,转换的目的是将两个值转换为相同的数据类型:
- 两个引用类型比较,只需判断它们是不是引用了同一个对象,是返回true,否则为false
- undefined 和 null 两者互相比较或者与自身比较,结果是true。它俩与其他任何值比较的都为false
- NaN与任何值比较包括它自身结果都是false
- String,Number,Boolean中的任意两个进行比较,最后都会转为Number类型再进行比较
- 引用类型和基本数据类型进行比较,两者最后都会转换成基本数据类型再进行比较
实例
// const a = ???
const a = {
i: 1,
valueOf: function () {
return this.i++
}
}
if(a == 1 && a == 2 && a == 3){
console.log("满足条件")
}
// 扩展
const b = {
i: 0,
list: [1, 2, 'lalala'],
valueOf: function () {
return this.list[this.i++]
}
}
if(b == 1 && b == 2 && b == 'lalala'){
console.log("满足条件")
}
原理解读
a 是一个对象,JavaScript中,当复杂类型和基本数据类型做比较时,会先调用复杂类型的valueOf方法,获取类型的原始值,如果得到的是一个string类型则直接返回原始值,如果得到的不是一个string类型,则继续调用toString方法,得到string类型之后返回。
使用重写对象的toString方法也可以:
// const a = ???
const a = {
i: 1,
toString: function () {
return this.i++
}
}
if(a == 1 && a == 2 && a == 3){
console.log("满足条件")
}
使用Object.defineProperty
通过劫持window对象,每次读取a属性时,都给 _a 增加1
let _a = 1
Object.defineProperty(window, 'a', {
get() {
return _a++
}
})
if (a == 1 && a == 2 && a == 3) {
console.log("满足条件")
}
使用Proxy
还有另一种劫持数据的方式,Vue3也是将响应式原理中的数据劫持Object.defineProperty换成了Proxy
let a = new Proxy({ i: 1 }, {
get(target) {
return () => target.i++
}
})
if (a == 1 && a == 2 && a == 3) {
console.log("满足条件")
}