關於如何使`(a === 1 && a === 2 && a === 3)`返回`true`問題的思考

Shapeying發表於2018-12-27

看見這個面試題目,第一反應就是在變數a取值時進行了一些改變,那就要用getter,關於存取器的介紹可以看這裡

var temp = 1;
Object.defineProperty(window, `a`, {
    get: function() { // 每次取值,temp+1
        return this.temp++
    }
});

console.log( a === 1 && a === 2 && a === 3); // true
console.log(a) // 4

同樣的問題是使 (a == 1 && a == 2 && a == 3) 返回true,不同點是,這裡是==,而不再是===

===恆等運算子在比較過程中,不會有任何型別轉換
==相等運算子比較寬鬆,如果兩個運算元不是同一型別,那麼相等運算子會嘗試進行一些型別轉換,然後進行比較。轉換規則如下:

  1. 如果一個是null,一個是undefined,則它們相等
  2. 如果一個是數字,一個是字串,先將字串轉換成數字,然後使用轉換後的值進行比較
  3. 如果其中的一個值為true,則轉換成1再進行比較;如果其中一個值為false,這轉換成0再進行比較
  4. 如果一個值是物件,另一個值是數字或者字串,則將物件轉換成原始值再進行比較。轉換成字串時,會先呼叫toString(),如果沒有toString()方法或者返回的不是一個原始值,則再呼叫valueOf(),如果還是不存在或者返回不是原始值,則會丟擲一個型別錯誤的異常。返回的原始值會被轉換成字串;如果轉換成數字時,也是類似的,不過是會先呼叫valueOf(),再呼叫toString(),返回的原始值會被轉換成數字
  5. 其他不同型別之間的比較均不相等

更詳細的資料型別轉換可以看 這裡

回到題目中,除了第一種使用getter的思路外,可以將a作為一個物件,而它的在比較中會轉換成數字,所以可以重寫valueOf()方法,在每次取值的時候,進行一些處理。

let a = {
    temp:1,
    valueOf:function(){
        return this.temp++
    }
}

console.log(a == 1 && a == 2 && a == 3); // true
console.log(a) {temp:4,valueOf: f ()}

以上是關於這個問題的兩種思路,當然還有還有我不知道的其他的做法,以後再補充

相關文章