js中有7種數(shù)據(jù)類型,可以分為兩類:
- 基礎(chǔ)類型(原始值):
Undefined、Null、String、Number、Boolean、Symbol(es6新出的) - 復(fù)雜類型(對(duì)象值):
object
什么情況下能正確打印‘success’?
var a = ???
if(a == 1 && a == 2 && a == 3 ){
console.log('success')
}
- 關(guān)系運(yùn)算符:會(huì)把其他數(shù)據(jù)類型轉(zhuǎn)換成
number之后再比較關(guān)系 - 首先我們排除掉原始數(shù)據(jù)類型(Undefined、Null、Boolean、Number 和 String、Symbol),a應(yīng)該是個(gè)復(fù)雜數(shù)據(jù)類型
- 復(fù)雜數(shù)據(jù)類型在隱式轉(zhuǎn)換時(shí)會(huì)利用
valueOf和toString,然后再轉(zhuǎn)成Number運(yùn)算(valueOf和toString是所有對(duì)象原型鏈頂層原型Object.prototype里的方法,所以每個(gè)對(duì)象都繼承這兩方法)
由此得知,我們可以重寫復(fù)雜數(shù)據(jù)類型在隱式轉(zhuǎn)換過程中所涉及的方法來達(dá)到效果
// 方法1
var a = {
i: 0,
valueOf() { // 這里的valueOf()也可以替換成toString()
return ++this.i
}
}
if(a == 1 && a == 2 && a == 3 ){
console.log('success')
}
// 方法2
var a = {
arr: [3, 2, 1],
valueOf() { // 這里的valueOf()也可以替換成toString()
return this.arr.pop()
}
}
if (a == 1 && a == 2 && a == 3) {
console.log('success')
}
在隱式轉(zhuǎn)換為number時(shí),執(zhí)行以下流程:
1、如果當(dāng)前值已經(jīng)是一個(gè)原始類型,則直接返回它
2、否則,如果當(dāng)前值是一個(gè)對(duì)象,則先調(diào)用valueOf()方法,如果結(jié)果是原始類型則直接返回
3、否則,調(diào)用這個(gè)對(duì)象的toString()方法,如果結(jié)果是原始類型,則返回toString()結(jié)果
4、否則,拋出TypeError異常
具體隱式轉(zhuǎn)換規(guī)則可參考here
- 所以上題在運(yùn)行時(shí)會(huì)先判斷 a 的類型,此時(shí)
typeof a('object'),不是原始類型,因此會(huì)先調(diào)用a.valueOf() - 由于我們重寫了
valueOf(),因此會(huì)執(zhí)行重寫后的valueOf(),每一次都會(huì)(得到自增后的值)or(返回a.arr的尾元素,并更新a.arr),結(jié)果是原始類型所以不會(huì)再繼續(xù)調(diào)用toString() - 得出三次執(zhí)行結(jié)果為 1, 2, 3, 滿足條件
~~歡迎交流指正