隐式转换部分规则
JS中使用==
对两个值进行比较时,会进行如下操作:
- 将两个被比较的值转换为相同的类型。
- 转换后(等式的一边或两边都可能被转换)再进行值的比较。
比较的规则如下表(mdn)
为了让(a == 1
),a只有这几种:
为String时,并且可转换为数字1('1' == 1 => true
)
为Boolean时,并且可转换为数字1 (true == 1 => true
)
为Object时,通过转换机制
后,可转换为数字1 (请看下文
)
对象转原始类型,执行顺序如下:
- Symbol.toPrimitive
- valueOf
- toString
- 报错
const obj = {
value: 1,
valueOf() {
return 2
},
toString() {
return '3'
},
[Symbol.toPrimitive]() {
return 4
}
}
obj == 4 // true
// 您可以将Symbol.toPrimitive、toString、valueOf分别注释掉验证转换规则
方法1 (with)
let i = 1
with ({
get a() {
return i++
}
}) {
if (a == 1 && a == 2 && a == 3) {
console.log('去吧,皮卡秋')
}
}
方法2 (Symbol.toPrimitive)
const a = {
i: 1,
[Symbol.toPrimitive]() {
return this.i++
}
}
if (a == 1 && a == 2 && a == 3) {
console.log('去吧,皮卡秋') // 去吧,皮卡秋
}
方法3 (valueOf 或 toString)
let a = {
i: 1,
valueOf() {
return this.i++
}
}
if (a == 1 && a == 2 && a == 3) {
console.log('去吧,皮卡秋') // 去吧,皮卡秋
}
方法4 (Array && join)
数组对象在进行隐式转换时,调用toString
时还会调用join
方法。
let a = [1, 2, 3]
a.join = a.shift
if (a == 1 && a == 2 && a == 3) {
console.log('去吧,皮卡秋') // 去吧,皮卡秋
}
方法5(Object.defineProperty)
let _a = 1
Object.defineProperty(window, 'a', {
get() {
return _a++
}
})
if (a == 1 && a == 2 && a == 3) {
console.log('去吧,皮卡秋') // 去吧,皮卡秋
}
方法6 (Proxy)
let a = new Proxy({
i: 1 }, {
get(target) {
return () => target.i++
}
})
if (a == 1 && a == 2 && a == 3) {
console.log('去吧,皮卡秋') // 去吧,皮卡秋
}