a 可以同時 == 1 && == 2 && == 3嗎?

作者:魚頭的Web海洋 公號 / 陳大魚頭

此題目的答案可以分為三大類:

  1. 類型轉換時的劫持
    首先我們要知道,在 JS 中類型轉換只有三種情況,分別是:

轉換為布爾值

轉換為數(shù)字

轉換為字符串

轉換為原始類型
對象在轉換類型的時候,會執(zhí)行原生方法ToPrimitive。

其算法如下:

如果已經(jīng)是 原始類型,則返回當前值;

如果需要轉 字符串 則先調(diào)用 toSting方法,如果此時是 原始類型 則直接返回,否則再調(diào)用 valueOf方法并返回結果;

如果不是 字符串,則先調(diào)用 valueOf方法,如果此時是 原始類型 則直接返回,否則再調(diào)用 toString方法并返回結果;

如果都沒有 原始類型 返回,則拋出 TypeError類型錯誤。

當然,我們可以通過重寫 Symbol.toPrimitive來制定轉換規(guī)則,此方法在轉原始類型時調(diào)用優(yōu)先級最高。

所以以此定義我們可以有以下四種答案:

?var a = {

   arr: [3, 2, 1],

   valueOf () {

       console.group('valueOf')

       console.log(this.arr)

       console.groupEnd('valueOf')

       return this.arr.pop()

   }

}

if (a == 1 && a == 2 && a == 3) {

   console.log('biu')

}

var b = {

   arr: [3, 2, 1],

   toString () {

       console.group('toString')

       console.log(this.arr)

       console.groupEnd('toString')

       return this.arr.pop()

   }

}

if (b == 1 && b == 2 && b == 3) {

   console.log('biu')

}

var c = {

   arr: [3, 2, 1],

   [Symbol.toPrimitive] () {

       console.group('Symbol.toPrimitive')

       console.log(this.arr)

       console.groupEnd('Symbol.toPrimitive')

       return this.arr.pop()

   }

}

if (c == 1 && c == 2 && c == 3) {

   console.log('biu')

}

var  d = [1, 2, 3]

d.join = d.shift

if (d == 1 && d == 2 && d == 3) {

   console.log('biu')

}

注:事實上,這四種可以算是同一種。關于最后一種,我們可以來看看ECMA中的 Array.prototype.toString() 定義:

定義 array 為 ToObject(thisvalue)(原生方法,將當前數(shù)組轉換成對象);

定義 func 為 Get(array,'join')(原生方法,在這一步調(diào)用 join 方法);

如果 IsCallble(func) (原生方法,判斷是否有內(nèi)部可調(diào)用的函數(shù))為 false,則 設置 func 原生函數(shù) %ObjProto_toString%(原生函數(shù), toString 的具體實現(xiàn));

返回 Call(func,array)。

  1. 對 getter 的劫持
    所謂的 getter 就是對象屬性在進行查詢時會被調(diào)用的方法 get,利用此函數(shù)也可以實現(xiàn)題目功能。

代碼如下:

window.val = 0

Object.defineProperty(window, 'd', {

   get () {

       return ++this.val

   }

})

if (d == 1 && d == 2 && d == 3) {

   console.log('biu')

}

const e = new Proxy({}, {

 val: 1,

 get ()  {

   return () => this.val++;

 }

});

if (e == 1 && e == 2 && e == 3) {

   console.log('biu')

}
  1. 正則表達式
    JS 中的 RegExp.prototype.exec() 作用是在一個指定字符串中執(zhí)行一個搜索匹配,返回一個結果數(shù)組或 null。

當正則表達式使用 " g" 標志時,可以多次執(zhí)行 exec 方法來查找同一個字符串中的成功匹配。當你這樣做時,查找將從正則表達式的 lastIndex 屬性指定的位置開始。( test() 也會更新 lastIndex 屬性)。

lastIndex 是正則表達式的一個可讀可寫的整型屬性,用來指定下一次匹配的起始索引。只有正則表達式使用了表示全局檢索的 " g" 標志時,該屬性才會起作用。

注:只有正則表達式使用了表示全局檢索的 " g" 標志時,該屬性才會起作用。

綜上所述,我們可以有方案如下:

var f = {

   reg: /\d/g,

   valueOf () {

       return this.reg.exec(123)[0]

   }

}

if (f == 1 && f == 2 && f == 3) {

   console.log('biu')

}

注:上述方法其實也利用了類型轉換的特點。然后暫時就寫下以上三種答案,不知道聰明的你是否還有別的解法呢?

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容