前端進階之 a 能夠同時 == 1 && == 2 && == 3嗎?

  • 做者:陳大魚頭
  • github: KRISACHAN
  • 連接:github.com/YvetteLau/S…
  • 背景:最近高級前端工程師 劉小夕github 上開了個每一個工做日佈一個前端相關題的 repo,懷着學習的心態我也參與其中,如下爲個人回答,若是有不對的地方,很是歡迎各位指出。

此題目的答案能夠分爲三大類:javascript

1. 類型轉換時的劫持

首先咱們要知道,在 JS 中類型轉換隻有三種狀況,分別是:前端

  • 轉換爲布爾值
  • 轉換爲數字
  • 轉換爲字符串

轉換爲原始類型

對象在轉換類型的時候,會執行原生方法ToPrimitivejava

其算法以下:git

  1. 若是已是 原始類型,則返回當前值;
  2. 若是須要轉 字符串 則先調用toSting方法,若是此時是 原始類型 則直接返回,不然再調用valueOf方法並返回結果;
  3. 若是不是 字符串,則先調用valueOf方法,若是此時是 原始類型 則直接返回,不然再調用toString方法並返回結果;
  4. 若是都沒有 原始類型 返回,則拋出 TypeError類型錯誤。

固然,咱們能夠經過重寫Symbol.toPrimitive來制定轉換規則,此方法在轉原始類型時調用優先級最高。github

因此以此定義咱們能夠有如下四種答案:正則表達式

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 ( ) 定義:算法

  1. 定義 arrayToObject(this value)(原生方法,將當前數組轉換成對象);
  2. 定義 funcGet(array, 'join')(原生方法,在這一步調用 join 方法);
  3. 若是 IsCallble(func) (原生方法,判斷是否有內部可調用的函數)爲 false,則 設置 func 原生函數 %ObjProto_toString%(原生函數,toString 的具體實現);
  4. 返回 Call(func, array)

2. 對 getter 的劫持

所謂的 getter 就是對象屬性在進行查詢時會被調用的方法 get,利用此函數也能夠實現題目功能。數組

代碼以下:微信

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')
}
複製代碼

3. 正則表達式

JS 中的 RegExp.prototype.exec() 做用是在一個指定字符串中執行一個搜索匹配,返回一個結果數組或 null前端工程師

當正則表達式使用 "g" 標誌時,能夠屢次執行 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')
}
複製代碼

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



若是你、喜歡探討技術,或者對本文有任何的意見或建議,你能夠掃描下方二維碼,關注微信公衆號「 魚頭的Web海洋」,隨時與魚頭互動。歡迎!衷心但願能夠碰見你。

相關文章
相關標籤/搜索