前端面試每日一題(總結版)

這裡是每日一題的匯總版,首發於 b 站動態,每日一題,在不知不覺中學到前端知識,每天更新。

2020年4月20日(typeof能判斷出哪些數據類型?)

typeof能判斷出哪些數據類型?
typeof能直接判斷出 Number,String,Boolean,undefined,Symbol
typeof(null)返回 object,判斷數組和對象返回 object,判斷函數返回 function

2020年4月21日 (CSS 中盒模型有幾種,有什麼不同?)

CSS 中盒模型有幾種,有什麼不同?
CSS 盒模型分為 W3C 標準盒模型和 IE 模型,W3C 標準盒模型中有元素的寬度 width 還有 border,padding, margin,其中 content 的高度和寬度不包含 padding 和 border。
IE 盒模型中也有這幾種屬性,但是 content 包含 padding 和 margin。

2020年4月22日 (new 操作符)

使用 new 創建對象時,new 運算符做了哪些事?

  1. 創建一個新對象
  2. 將構造函數的作用域賦給新對象(this 就指向了這個新對象)
  3. 執行構造函數中的程式碼(初始化對象)
  4. 返回新對象

2020年4月23日(值類型和引用類型的區別)

值類型和引用類型的區別?

值類型是不可變的數據類型,例如 let a = 10; 在記憶體中的執行過程是先創建一塊記憶體空間存儲 10,然後再令 a 指向這塊記憶體空間。如果這時候令 a=20; 會在記憶體中再開闢一段記憶體空間裡面存放 20,然後將 a 指向這段記憶體空間,之前的那個記憶體空間會被銷毀。所以值類型是不可變的,要想改變必須將之前的銷毀然後創建新的記憶體空間。

引用類型是可變的數據類型,例如 obj = { x: 1} 在記憶體中 obj 中存放的是 { x: 1 } 這個對象的地址,這個對象是在堆中存儲的,通過 obj.x=3 改變對象的屬性,這個時候並不會將之前的對象銷毀,因此引用類型是可變的數據類型。

2020 年4月24日(<!DOCTYPE>的作用)

注意 <!DOCTYPE> 並不是 HTML 標籤。

總結來說有這兩個作用:

1)聲明文檔的類型,

2)告訴瀏覽器應該以什麼樣的標準解析這個文檔

瀏覽器有兩個模式,怪異模式和標準模式,聲明 <!DOCTYPE html> 作用就是告訴瀏覽器你即將要處理的是 HTML 文檔,並且在渲染文檔時要按照標準模式的方式。

MDN 解釋

HTML中,文檔類型聲明是必要的。所有的文檔的頭部,你都將會看到”<!DOCTYPE html>” 的身影。這個聲明的目的是防止瀏覽器在渲染文檔時,切換到我們稱為「怪異模式(兼容模式)」的渲染模式。「<!DOCTYPE html>” 確保瀏覽器按照最佳的相關規範進行渲染,而不是使用一個不符合規範的渲染模式。

2020年4月25日(語義化標籤的理解)

語義化標籤的理解

按照字面意思理解就是有語義的標籤,要做到用最合適的標籤做最合適的事,例如要做一個導航欄,要用 Nav 而不是 div。

使用語義化標籤有很多好處:

開發者看到文檔後能夠做到見名知義,有利於團隊維護和開發。

能讓頁面呈現清晰的結構,機器更容易理解,有利於爬蟲和搜索引擎的抓取(SEO的優化)

CSS 選擇器優先順序

!importtant 優先順序最高 > 內聯樣式 > ID 選擇器 > 類,屬性,偽類 > 元素,偽元素

注意點:不會進位,一萬個類選擇器也抵不上一個id選擇器,相同權重,後寫的生效。

2020年4月26日(new 運算符的底層程式碼實現)

new 運算符的底層程式碼實現

// func 為傳入的構造函數
const new2 = fucntion (func) {
  const o = Object.create(func.prototype);
  const k = func.call(o);
	return k === 'object' ? k : o;
}

上面這種寫法沒有考慮帶參數的情況。

2020年4月27日(CSS 對於選擇器的解析順序)

今天的每日一題和大家分享一下 CSS 對於選擇器的解析順序。

以一段程式碼為例:

body div .hello {
  color: #ccc;
}

按照我們正常的思維是瀏覽器會選取尋找 body,然後再去找 body 下的 div,然後再去找 div 下的 .hello 類。但是瀏覽器與這個過程正好相反,它會先去找到 .hello 這個類,然後再去驗證它有一個父元素是 div,然後 div 再驗證它是否有一個父元素是 body。

之所以按照這樣的流程是出於性能的考慮,如果是第一種方式,找 body 下的 div 時有可能有特別多的 div,然後再在這些 div 中尋找 .hello 類時是非常耗時的。

2020 年4月28日(CSS 中清除浮動常用的兩種方法)

今天和大家分享一下 CSS 中清除浮動常用的兩種方法,學累了就來看看吧。

CSS 清除浮動

  1. 父元素觸發 BFC(例如可以採用 overflow:hidden 使父元素觸發 BFC)

  2. 利用偽元素,給父元素的最後面添加一個偽元素,令偽元素 clear: both,這樣就會使得左右兩邊都沒有浮動元素,又因為它是父元素的最下面的一個元素,所以它只能在父元素的最下面並且左右都沒有浮動元素,這樣浮動元素就在它的上面,父元素就不會發生告訴塌陷了。

    程式碼示例:

    父元素::after {
      content: '';
      clear: both; /* 使左右兩邊沒有浮動元素 */
      display: block;
      visibility: hidden;
      height: 0;
    }
    

2020年4月29日(JS 任務隊列)

今天和大家來一起學習一下 JavaScript 事件循環機制中的任務隊列。

任務隊列分為兩種,一種是micro task,另一種是 macro-task。

macro-task大概包括:script(整體程式碼), setTimeout, setInterval, setImmediate, I/O, UI rendering。

micro-task大概包括: process.nextTick, Promise, Object.observe(已廢棄), MutationObserver(html5新特性)

優先順序: micro-task > macro-task;

推薦給大家一個影片,生動形象。 兩分鐘了解 JavaScript EventLoop //www.bilibili.com/video/BV1kf4y1U7Ln

2020年4月30日(GET 和 POST 的區別)

今天和大家一起來學習一下面試中經常問的 GET 和 POST 的區別,主要有以下幾點。

1)GET 在瀏覽器回退時是不會再次發送 GET 請求的,POST 會再次發送請求

2)GET 請求會被瀏覽器主動快取,而 POST 不會,除非手動設置(在地址欄中輸入url的方式只能發送 GET 請求)

3)GET 請求的參數會被完整保留在瀏覽器歷史記錄里,而 POST 請求中的參數不會被保留

4)GET 請求在 URL 中傳送的參數是有長度限制的,而 POST 沒有限制

5)GET 參數通過 URL 傳遞,POST 數據放在 Request body 中

6)GET 比 POST 安全性低,因為參數直接暴露在 URL 上,所以不能用來傳遞敏感資訊

2020 年5月1日(HTTP 中常用的一些狀態碼)

今天和大家一起來學習一下 HTTP 中常用的一些狀態碼。

200 OK 請求成功

206 Partial Content 客戶端發送了一個帶有 Range 頭的 GET 請求,服務端成功響應了該請求。在客戶端請求一個影片文件的時候,服務端一般都會返回一個 206,表示將部分資源返回給客戶端。

301 Moved Permanently 所請求的資源已被永久地移到別的地方。服務端需要在響應的首部添加一個 Location 屬性來表示資源已經被移動到哪個 url 。(Location屬性是可選的,但是推薦有)

302 Found 所請求的資源被臨時移動到別的地方。服務端需要在響應的首部添加 Location 屬性來臨時定位那個資源。將來還是應該用老的 url 進行訪問。(Location屬性是可選的,但是推薦有)

304 Not Modified 請求的資源在本地有並且和服務端上的資源一致並沒有被修改。

400 Bad Request 告知客戶端發送了一個錯誤的請求,服務端不能理解

401 Unauthorized 請求未經授權,這個狀態碼必須和 WWW.Authenticate 報頭域一起使用 403 Forbidden 請求的資源被禁止訪問。

404 Not Found 請求的資源不存在

500 Internal Server Error 伺服器發生不可預期的錯誤原來的緩衝文檔還可以繼續使用

503 Server Unavailable 伺服器現在無法為請求提供服務,將來可能可以。如果伺服器知道將來什麼時候可以提供服務,可以在響應的首部添加一個 Retry-After 屬性告訴客戶端什麼時候可以再次提供服務。

2020年5月2日(call,apply,bind 之間的區別)

今天和大家聊一下 call,apply,bind 之間的區別?

先來看一下相同點:

它們三個都是改變函數運行時內部 this 的指向,第一個參數指定的對象就是函數運行時 this 指向的對象。

再來看一下不同點:

call 的第二個參數是參數列表的形式,調用 call 的函數會立即執行。

fn1.call(obj, 1, 2, 3)

apply 的第二個參數是一個數組,調用 apply 的函數也會立即執行。

fn1.apply(obj, [1, 2, 3])

bind 的第二個參數是參數列表的形式,調用 bind 的函數會返回一個函數,而不是立即執行。

fn1 = fn1.bind(obj, 1, 2, 3)   // 將 fn1 內部的 this 指向 obj,並且返回綁定後的函數
fn1() 

2020年5月3日(比較兩個對象的內容是否相等)

由於自己做的一個鍵盤導航組件中需要用到比較兩個對象的內容是否相等,因此根據深拷貝的思想寫了一個函數分享給大家,大家可以順便複習一下深拷貝。(b 站不支援 MarkDown太不方便了,直接粘貼成圖片了,程式碼可以在直播頁面上的 GIthub 倉庫中獲取)

判斷兩個對象的內容是否相等

2020年5月4日(位元組筆試分享)

今天做了位元組的筆試,客觀題只有五道選擇題,一個問答題,還有三道編程題。選擇題考查的外邊距重疊,事件循環機制(場景題讓你寫輸出),object.keys 的返回值(只是一個選項),window.postMessage() 跨域,JSONP 跨域只能發送 GET 請求等。

問答題是給你一段程式碼,讓你找出其中的錯誤,並修正,然後針對這個問題讓你寫出儘可能多的方案。剛開始沒有 Get 到考察的點,後來意識到考察的是 this 並不會遵循作用域鏈的規則,因此需要 const that = this,然後在子函數中利用 that 才能訪問到父函數中的 this。

關於儘可能多的方案,題目中使用兩個 class 來實現的,我使用借用構造函數,藉助原型鏈,組合模式這幾種都實現了一下。

關於編程題,難度 LeetCode 中等難度上下,平時一定要多刷點題,還有在在線下多練習一下各種形式的輸入讀取和各種形式的輸出,到時候可以把精力都放在演算法上。