「敲黑板」JS 類型轉換及訪問攔截

前言

面試的時候,你會遇到許多奇奇怪怪的問題。就好像上學的時候,你在數學課本里學習了等邊三角形的三個內角都是等於 60 度,你不多能見到卷子裏直接問你等邊三角形的三個內角是多少度。多數狀況下這個知識點會被嵌套在一個幾何題裏,做爲一個論證依據,若是你不知道這個知識點,那就解答不出這道題。javascript

前端面試的時候,面試官問你奇奇怪怪的問題,你可能以爲,我寫業務根本用不上這些鳥東西。若是你的思想停留在這個位置,那可能你也就只能停留在切圖仔這個層面。前端

dasfad.gif

類型轉換

問:a == 1 && a == 2 && a == 3,如何讓其返回 true?java

看到這個問題,我一開始是不知所措的,a 如果一個常量,那麼它必然某個值,爲什麼能同時等於 3 個值。正當我百思不得其姐的時候,我再次認真的審題,a 在這條表達式中有一個動做,就是去和 123 依次作了判讀是否相等,在 JS 中,兩個不一樣類型的值在判斷是否相等的時候,都會作一次轉換,咱們能不能控制這個轉換的方法,而且返回新的值呢?咱們嘗試以下代碼:面試

var a = {
  toString: function() {
    console.log('轉換')
  }
}
a == 1
// 轉換
// false
a == '1'
// 轉換
// false
a == {}
// false
a == []
// false
複製代碼

如上述代碼所示,咱們重寫對象 atoString方法。性能優化

  • 當對象 a 和一個數字 1 作比較的時候,執行了 atoString 方法。
  • 當對象 a 和一個字符串 1 作比較的時候,執行了 atoString 方法。
  • 當對象 a 和一個空對象作比較的時候,未執行 atoString 方法。

知識點:這即是 JS 的類型轉換,引用類型在和基礎類型作比較的時候,會先通過 toString 方法作類型轉換。markdown

全部引用類型的隱式原型下,都有一個 toString 方法,以下圖所示:架構

image.png

那麼,上述的考題就好解決了,思路大概就是,設置 a 變量爲一個對象,重寫對象的 toString 方法,大體以下所示:函數

var a = {
  value: 0,
  toString: function() {
    return ++this.value
  }
}

a == 1 && a == 2 && a == 3
// true
複製代碼

每次對比的時候,都會觸發 toString 方法,返回自增後的值,依次加到 3 爲止,最後返回 truepost

這裏穿插一個小知識,上述重寫 toString 不要用箭頭函數,若是使用箭頭函數,函數內的 this 將會指向全局 window 對象,箭頭函數的 this 永遠只想第一個包裹它的正常函數,逐級往上找,直到 window 全局對象。因此上述代碼若是寫了箭頭函數,this.value 至關於 window.value,返回 undefiend性能

Object.defineProperty

若是咱們將考題變種,問:a === 1 && a === 2 && a === 3,如何讓其返回 true?

此時你心想,狗日的,什麼亂七八糟的。沒錯,此時的你只能以不變應萬變,那就是夯實本身的 JS 基礎。變種考題和以前的區別在於,用了嚴格模式的 === ,它是不會觸發類型轉換調用 toString

解決上述問題。能夠上 gettergetter 的做用就是當你訪問變量的時候,會被攔截。如上述表達式,當執行到 a 的時候,其實就訪問了 a 變量,那麼咱們引出 Object.defineProperty ,代碼以下:

var value = 0
Object.defineProperty(window, 'a', {
  get() {
    return ++value
  }
})

a === 1 && a === 2 && a === 3 // true
複製代碼

第一次對比 a === 1 此時訪問了 a 變量,get 方法執行,返回 1。以此類推,最後 a3

總結

這些題目不是重點,重要的是這些題目背後所帶出的 JS 知識。你可能以爲我平時業務開發基本上用不上這些知識點,可是真到了寫一些上層架構的時候,這些基礎知識,將會是你獲取更多機會和財富的敲門磚,我不敢保證給你們出一個系列專欄,儘可能保持周更吧,平時是真滴忙。

llq.gif

往期好文推薦

打通任督二脈的前端環境變量 — env 點贊數👍 228

Vite 2.0 + React + Ant Design 4.0 搭建開發環境 點贊數👍 385

面不面試的,你都得懂原型和原型鏈 點贊數👍 593

Vue 3 和 Webpack 5 來了,手動搭建的知識該更新了 點贊數👍 521

換一個角度分析,網頁性能優化 點贊數👍 200

你好,談談你對前端路由的理解 點贊數👍 625

之前我沒得選,如今我只想用 Array.prototype.reduce 點贊數👍 588

無處不在的發佈訂閱模式 —— 此次必定 點贊數👍 164

聊聊 JSX 和虛擬 DOM 點贊數👍 110

相關文章
相關標籤/搜索