記一道前端經典面試題

以下所示:前端

問: a等於多少時, 下方的條件才成立
        var a = ?;
        if (a == 1 && a == 2 && a == 3) {
          console.log(1)
        }

這題比較有意思啊,相信不少前端同窗都看過。它的解法有不少,本篇列出我所知道的幾種方式。
不少人第一眼看到這道題可能會認爲a=true時,便可知足。可是並不對。由於==雙等號在比較時, 會進行隱式類型轉換。在轉換時分幾種狀況:數組

1 . 對象 == 字符串
會調用對象的 toString()方法後 和字符串作比較
對象.toString() == string
2 . null == undefined
只有在 雙等號狀況下才是true

3 . NaN == NaN
NaN和任何數據 包括它本身都不相等 返回falsethis

4 . 剩餘狀況
剩下的比較都會轉換爲數字再進行比較code

因此說 將a=true 並不能知足條件。由於true轉換爲數字爲1,那麼1 == 1 可是1 !== 21 !== 3對象

因此得想其餘方法字符串


方法1
重寫對象內部的.toString()方法
var a = {
  _key: 0,
  toString() {
    return ++this._key
  }
}

if (a == 1 && a == 2 && a == 3) {
  console.log(1)
} 
// 打印結果
// 1

以上代碼成功打印結果1。該方法利用了對象轉換爲數值過程當中會先調用對象內部的toString()方法。 咱們對toString()方法進行重寫,經過一個_key來保存每次累加的結果。每調用一次重寫後的toString()方法_key值都會+1。即知足if條件。get


方法2
將toSting()方法重寫爲數組的shift()方法
var a = [1,2,3];
a.toString = a.shift;

if (a == 1 && a == 2 && a == 3) {
  console.log(1)
} 
// 打印結果
// 1

其實該方法也是重寫了toString()方法。只不過將toString()重寫爲了數組的shift()方法。shift方法刪除數組的第一項並返回該項
數組轉數值的過程當中也會調用toString()方法,由於a.toString = a.shift,因此每次調用的都是shift()方法。每次都會刪除數組的第一項並返回,保證每次toString()的返回值都不同string


方法3
數據劫持 Object.defineProperty()
var temp = 0;
Object.defineProperty(window, 'a', {
  get() {
    // 此處注意 在get攔截器中 不能獲取當前屬性a
    // 否則會形成死循環 報錯
    return ++temp;
  }
})

if (a == 1 && a == 2 && a == 3) {
  console.log(1)
}
// 打印結果
// 1
相似 ES6中proxy,使用 ES5中的defineProperty監聽obj中的name屬性。使用一個 臨時變量temp來累加,每次只要 監聽a都會返回累加後的值。固然也是有缺點,若是是經過 let 聲明的變量就不能用該方法了,由於 let聲明的變量並無放到window上,因此也無從監聽。
相關文章
相關標籤/搜索