由於目前現在求職市場競爭激烈,許多初學者和經驗豐富的開發人員都面臨着求職問題。因此,最好的方法是不斷學習並提高自己的技能。為了拿到心儀的offer,我們需要認真準備面試,因此,今天我為大家準備了53道面試題,我以“一問一答”的形式將這些前端面試題分享出來,希望能夠幫助到你。雖然這些面試題主要針對初級開發人員,但其中也有包括一些中級開發人員的題。那麼,我們現在開始吧。1. JavaScript 中有哪些數據類型?

  • Number — 數字
  • String — 字符串
  • Boolean — 布爾類型,true 或 false
  • Object — JavaScript 對象
  • null — 表示“無”、“空”或“未知值”的特殊值。
  • undefined ——“值尚未被分配”。如果聲明瞭變量但沒有分配值,則分配此類型。
  • Symbol— 一種唯一且不可變的數據類型,可用作對象屬性的標識符。
  • BigInt — 用於創建大數。

const bigInt = 1234567890123456789012345678901234567890n;2.“”和“=”有什麼區別? 運算符“”檢查抽象相等,而“=”檢查嚴格相等。換句話説,“”運算符在比較之前執行必要的類型轉換,而“=”則不執行類型轉換。因此,如果兩個值不是同一類型,則使用“===”運算符時將返回 false。

3. 變量的聲明方式有哪些?

聲明變量有 4 種方法:聲明變量有 4 種方法:

foo =123;var foo = 123;let a = 123;conest a = 123;

使用“var”關鍵字聲明變量與第一種方法類似。 以這種方式聲明的變量具有全局或函數作用域,但缺少塊作用域,這是一個缺點。

“let”和“const”是聲明變量的更好方法。 它們具有塊作用域,這意味着在函數內部聲明的變量在該函數外部將不可見。

“const”變量是不可變的,但如果它是一個對象,你可以改變它的屬性,如果它是一個數組,你可以修改和添加元素。

4. null 和 undefined 有什麼區別?

兩個選項都代表空值。 如果我們初始化一個變量但不給它賦值,它就會被分配一個特殊的標記—undefined。Null 是手動分配的。Null 是一個特殊值,表示“無”、“空”或“未知值”。 如果我們需要清除變量的值,我們設置 foo = null。

5. 箭頭函數以及與常規函數的區別。

  • 箭頭函數不能使用參數對象。
  • 它們有不同的語法。
  • 箭頭函數沒有自己的 this 上下文。 當引用 this 時,箭頭函數從周圍的作用域中獲取上下文。
  • 箭頭函數不能用作構造函數。 換句話説,它們不能用 new 關鍵字調用。

6. 什麼是閉包?以及為什麼需要它們?

閉包是一個函數以及它可以訪問的所有外部變量。 例如,有一個具有嵌套函數的函數,該函數將關閉並保留其父級的變量。

javascript - 前端面試試題收集 - 個人文章_#開發語言

7. 什麼是模板文字?

模板文字用反引號 (") 括起來,並允許多行字符串。 它們還允許在其中嵌入表達式。

javascript - 前端面試試題收集 - 個人文章_#javascript_02

8. 什麼是Set和Map?

Map是一個集合,是一種按照鍵值對原理進行操作的數據結構,類似於Object。 然而,Map 和 Object 之間的主要區別在於 Map 允許使用任何類型的鍵。Set 是一種沒有鍵的集合類型,是一個數組,其中每個值只能出現一次。 集合在其內部存儲唯一的值。

9. 如何檢查對象中是否存在屬性?

第一種方法是使用 hasOwnProperty 函數,該函數適用於每個對象。第二種方法是使用 in 運算符。 但是,在使用 in 運算符時必須小心,因為它會檢查鏈中的所有原型。

javascript - 前端面試試題收集 - 個人文章_#javascript_03

10. 如何訪問對象屬性?

第一種方式是靜態的,使用點表示法:obj.a。

第二種方式是動態的,使用方括號:obj[‘a’]。

javascript - 前端面試試題收集 - 個人文章_#vue.js_04

11. 使用數組的主要方法有哪些?

  • forEach — 用於循環數組的迭代方法,不返回任何內容。 它提供了比常規 for 循環更優雅的替代方案。
  • filter(callback, [args]) — 一種使用提供的函數過濾數組的方法。 它創建一個新數組,其中僅包含回調(item, i, arr) 函數返回 true 的原始數組中的元素。
  • map(callback, [args]) — 一種轉換數組的方法。 它創建一個新數組,其中包含為數組的每個元素調用回調(item, i, arr) 函數的結果。
  • reduce(callback, [initValue]) — 一種按順序處理數組的每個元素,同時維護中間結果的方法。

12.創建對象的方式有哪些?

使用構造函數:

javascript - 前端面試試題收集 - 個人文章_#面試_05

使用對象文字表示法:

javascript - 前端面試試題收集 - 個人文章_#開發語言_06

使用一個類:

javascript - 前端面試試題收集 - 個人文章_#vue.js_07

使用創建函數:

javascript - 前端面試試題收集 - 個人文章_#面試_08

13.什麼是Promise?

Promise 是一個設計用於處理異步代碼的對象。它維持自己的狀態。最初,Promise 處於待處理狀態,如果異步代碼執行成功,則 Promise 轉換為已完成狀態;如果發生錯誤,則轉換為拒絕狀態。Promise 接受兩個回調函數:

  • onFulfilled,當Promise履行時觸發。
  • onRejected,當Promise被拒絕時觸發。

使用模式如下:

  • 需要異步執行某些操作的代碼會創建一個 Promise 並返回它。
  • 外部代碼收到 Promise 後,將 onFulfilled 和 onRejected 回調函數傳遞給它。
  • 該過程完成後,異步代碼將 Promise 轉換為已完成或已拒絕狀態,並自動調用相應的回調函數。****

14.什麼是async/await以及如何使用它?

async/await 是一種處理 Promise 的特殊語法。

使用異步語法聲明的函數始終返回 Promise。

關鍵字await使JavaScript解釋器等待,直到await右側的Promise完成後才繼續執行。然後,它將返回結果,並且代碼將繼續執行。wait 不能在常規函數中使用。

15. 如何檢查一個對象是否是數組?

要檢查對象是否是數組,可以使用 Array.isArray() 方法。它接受一個對象作為輸入,如果該對象是數組則返回 true,如果不是數組則返回 false。

javascript - 前端面試試題收集 - 個人文章_#vue.js_09

16. 擴展運算符 (…) 的目的是什麼?

擴展運算符 (…) 用於解包數組或對象。

它允許你擴展可迭代的元素,例如,數組和字符串。

它用在調用的預期參數數量為零或更多的函數中。

它用在數組文字或表達式中。

它用在對象文字中,其中鍵值對的數量應為零或更多。

javascript - 前端面試試題收集 - 個人文章_#開發語言_10

17. 複製對象時如何避免引用依賴?

如果對象不包含嵌套對象,例如:

javascript - 前端面試試題收集 - 個人文章_#vue.js_11

在這種情況下,你可以使用展開運算符或 Object.assign() 方法:

javascript - 前端面試試題收集 - 個人文章_#javascript_12

如果對象包含嵌套對象:

javascript - 前端面試試題收集 - 個人文章_#前端_13

在這種情況下,你需要執行深複製。

解決方法雖然較慢,但是:

javascript - 前端面試試題收集 - 個人文章_#vue.js_14

該方法適用於沒有原型和函數的對象。

或者,你可以使用 lodash 庫的 deepClone() 函數。

18. 如何改變函數的上下文?

使用bind()方法,該方法返回一個帶有綁定上下文的新函數。

javascript - 前端面試試題收集 - 個人文章_#javascript_15

使用 call() 和 apply() 方法。主要區別在於 call() 接受參數序列,而 apply() 接受參數數組作為第二個參數。

javascript - 前端面試試題收集 - 個人文章_#前端_16

19. 什麼是三元運算符/條件運算符?

三元運算符是 if-else 語句的簡寫符號。運算符由問號和冒號表示。它被稱為三元,因為它是唯一接受三個參數的運算符。

健康)狀況 ?表達式_1:表達式_2

javascript - 前端面試試題收集 - 個人文章_#面試_17

20.什麼是解構?

解構是一種允許我們將數組和對象解包為多個變量的語法。

javascript - 前端面試試題收集 - 個人文章_#開發語言_18

21.什麼是DOM?

DOM 代表文檔對象模型。它是將 HTML 文檔表示為標籤樹。

例子

DOM 樹中的每個節點都是一個對象。

HTML 文檔的基本元素是標籤。

javascript - 前端面試試題收集 - 個人文章_#開發語言_19

根據文檔對象模型 (DOM),每個 HTML 標籤都是一個對象。嵌套標籤是其父元素的“子元素”。標籤內的文本也是一個對象。所有這些對象都可以使用 JavaScript 訪問,我們可以使用它們來操作頁面。

22.什麼是事件循環?

事件循環——一種管理代碼執行的機制。它以正確的順序處理事件處理和任務執行。

事件循環的主要思想是JavaScript在單線程環境中運行但可以處理異步操作。當異步操作(例如服務器請求)完成時,它將相應的事件放入事件隊列中。

事件循環以循環方式工作,按照事件到達的順序處理這些事件。

它從隊列中獲取一個事件並將其傳遞以供執行。如果事件包含回調或處理程序,則會調用它,並執行與該事件關聯的代碼。

事件循環還處理其他任務,例如計時器和微任務(Promise)。它管理所有這些任務的執行順序,以確保一致性並防止阻塞代碼執行的主線程。

簡而言之,JavaScript 中的事件循環通過處理隊列中的事件並按正確的順序執行相應的代碼來管理異步操作。這使得 JavaScript 在處理異步操作時能夠響應並有效地利用其資源。

javascript - 前端面試試題收集 - 個人文章_#前端_20

23.什麼是原型繼承?

JavaScript 中的每個對象都有一個屬性——原型。可以將方法和屬性添加到原型中。可以根據原型創建其他對象。創建的對象自動繼承其原型的方法和屬性。如果對象中不存在某個屬性,則將在原型中執行其搜索。

24.什麼是可選鏈運算符?

可選鏈接運算符 ?。如果 ? 後面的部分停止計算並返回undefined。undefined或為null。

讓我們考慮一個用户對象。大多數用户都有一個地址 user.address 和一個街道 user.address.street,但有些用户沒有提供地址。在這種情況下,可選鏈接運算符可以幫助我們在嘗試訪問未在地址中指定街道的用户街道時避免錯誤。

javascript - 前端面試試題收集 - 個人文章_#vue.js_21

25.什麼是 Shadow DOM?

Shadow DOM 是一組 Web 標準,允許封裝網頁上元素的結構和樣式。它代表 DOM 的一個特殊片段,位於元素內部並與頁面的其餘部分分開。Shadow DOM 用於創建具有獨立且風格化內容的組件和小部件,這些內容與頁面的整體結構不衝突。

26.什麼是遞歸?如何使用它?

遞歸是一種解決問題的方法,其中函數通過在自己的函數體內重用自身來解決問題。簡單來説,就是函數調用自身的時候。

遞歸函數包括:

  • 終止條件或基本情況
  • 遞歸步驟——一種將問題簡化為更簡單形式的方法。

javascript - 前端面試試題收集 - 個人文章_#開發語言_22

基本情況是必要條件;否則,會因函數調用無限循環而導致堆棧溢出。

27. 函數表達式和函數聲明有什麼區別?

函數聲明是聲明函數的傳統方式。

javascript - 前端面試試題收集 - 個人文章_#面試_23

函數表達式:

javascript - 前端面試試題收集 - 個人文章_#前端_24

通過函數聲明,可以創建函數並將其分配給變量,就像任何其他值一樣。本質上,函數如何定義並不重要,因為它是存儲在變量“foo”中的值。

然而,函數聲明是在執行代碼塊之前處理的,這意味着它們在整個代碼塊中都是可見的。另一方面,函數表達式僅在執行流到達時才會創建。

28.什麼是構造函數?

構造函數是用於創建對象的常規函數。但是,使用它們有兩個規則:

  • 構造函數的名稱應以大寫字母開頭。
  • 應使用 new 運算符調用構造函數。

javascript - 前端面試試題收集 - 個人文章_#前端_25

當使用 new 運算符創建構造函數時,會發生以下情況:

  • 創建一個新的空對象並將其分配給該對象。
  • 執行構造函數內的代碼。通常,此代碼將修改 this 對象並添加新屬性。
  • 返回此值。

29. 如何從對象中獲取鍵列表和值列表?

你可以使用 Object.keys() 獲取鍵列表,使用 Object.values() 獲取值列表。

javascript - 前端面試試題收集 - 個人文章_#vue.js_26

30. 提供 ES6 中新功能的示例。

最常見的:

  • let和const。引入新關鍵字 let 和 const 用於聲明具有塊作用域的變量。
  • 箭頭函數。箭頭函數的概念允許更簡潔和清晰的函數定義。

javascript - 前端面試試題收集 - 個人文章_#vue.js_27

  • 默認參數。你可以定義函數參數的默認值。

javascript - 前端面試試題收集 - 個人文章_#vue.js_28

  • 展開運算符 (…)。擴展運算符允許解包函數參數的數組或對象元素或創建新的數組/對象。

javascript - 前端面試試題收集 - 個人文章_#前端_29

  • 解構。解構允許從數組或對象中提取值並將它們分配給變量。

javascript - 前端面試試題收集 - 個人文章_#javascript_30

31. ES6中如何進行類繼承?

類繼承是使用“extends”關鍵字後跟父類的名稱來完成的。

javascript - 前端面試試題收集 - 個人文章_#開發語言_31

32. JavaScript 中的微任務和宏任務是什麼?

在 JavaScript 中,微任務和宏任務是指需要在事件循環中執行的任務類型。

微任務是在瀏覽器重新繪製頁面之前需要在當前事件循環內執行的任務。它們通常使用 Promise.then()、process.nextTick()(在 Node.js 中)或 MutationObserver 等方法添加到執行隊列中。

微任務的示例包括執行 Promise 處理程序和 DOM 突變。

另一方面,宏任務是在當前事件循環完成之後、在屏幕上呈現更改之前需要執行的任務。

這包括使用 setTimeout、setInterval、requestAnimationFrame 添加到事件隊列的任務,以及處理輸入事件和網絡請求。

宏任務在當前事件循環中的所有微任務處理完畢後執行。

微任務和宏任務之間的區別很重要,因為它決定了執行順序並允許管理 JavaScript 中不同任務的優先級。

微任務具有更高的優先級,並且在宏任務之前執行,這樣可以更快地更新界面並防止阻塞主 JavaScript 執行線程。

33.什麼是生成器?

生成器根據需要一個一個地生成一系列值。生成器可以很好地與對象配合使用,並且可以輕鬆創建數據流。

要聲明生成器,需要使用一種特殊的語法——生成器函數。

javascript - 前端面試試題收集 - 個人文章_#javascript_32

next() 是生成器的主要方法。調用時,next() 開始執行代碼,直到最近的yield 語句。該值可能不存在,在這種情況下它表示為未定義。當達到yield時,函數執行暫停,並將相應的值返回給外部代碼。

javascript - 前端面試試題收集 - 個人文章_#javascript_33

34.瀏覽器中存儲數據的方法有哪些?

在瀏覽器中存儲數據有多種方法:

  • LocalStorage 和 SessionStorage — 在瀏覽器中存儲鍵值對。其中存儲的數據在頁面刷新後仍保留。兩種存儲選項都只能使用字符串作為鍵和值,因此需要使用 JSON.stringify() 轉換對象。Cookie — 存儲在瀏覽器中的小數據字符串。
  • Cookie 通常由 Web 服務器使用 Set-Cookie 標頭設置。然後,瀏覽器將使用 Cookie 標頭自動將它們添加到幾乎每個對同一域的請求中。一個 cookie 最多可以容納 4kb 的數據。根據瀏覽器的不同,每個站點允許使用 20 個以上的 cookie。
  • IndexedDB — 內置數據庫,比 localStorage 更強大。它是一個鍵值存儲,其中有多種類型的鍵可用,值幾乎可以是任何東西。IndexedDB 支持事務以提高可靠性,支持鍵範圍查詢和索引,並允許存儲比 localStorage 更多的數據。IndexedDB 是為離線應用程序設計的,可以與 Service Workers 等技術結合。

35、sessionStorage和localStorage有什麼區別?

SessionStorage 和 localStorage 允許在瀏覽器中以鍵值格式存儲對象。

主要區別是:

  • localStorage 最多可以存儲 10 MB 的數據,而 sessionStorage 最多可以存儲 5 MB 的數據。
  • localStorage 中的數據不會被刪除,而 sessionStorage 中的數據會在瀏覽器選項卡關閉時被刪除。
  • localStorage 中的數據可以從任何窗口訪問,而 sessionStorage 中的數據只能從同一瀏覽器窗口訪問。

36.什麼是正則表達式?

正則表達式是由特殊規則和模式定義的字符串。它們是一個強大的工具,可以檢測和處理字符串中的複雜結構。

javascript - 前端面試試題收集 - 個人文章_#開發語言_34

37.WeakSet和WeakMap是** 什麼,它們與Map和Set有何不同?**

WeakMap 和 Map 之間的第一個區別是 WeakMap 中的鍵必須是對象,而不是原始值。

第二個區別在於數據結構的內存存儲。JavaScript 引擎將值保存在內存中,只要它們是可訪問的,這意味着它們可以被使用。

通常,對象屬性、數組元素或其他數據結構被認為是可訪問的,並且只要數據結構存在,它們就會保留在內存中,即使沒有其他對它們的引用。

對於 WeakMap 和 WeakSet 來説,它的工作方式不同。一旦對象變得不可訪問,它將從數據結構中刪除。

38. 為什麼兩個具有相同字段的對象比較時返回 false?

根據對內存區域的引用來比較對象。對於 JavaScript,test1 和 test2 對象是不同的,即使它們具有相同的字段。僅當對象是同一個對象時,它們才相等。

javascript - 前端面試試題收集 - 個人文章_#前端_35

39. 為什麼我們可以調用原始類型的方法?

JavaScript 允許使用原始數據類型(字符串、數字等),就像它們是對象一樣。原始數據類型有方法。

為了使此功能可用,每個基本數據類型都有自己的包裝對象:字符串、數字、布爾值和符號。由於這些包裝對象,原始數據類型具有不同的方法集,例如 toLowerCase() 或 toUpperCase()。

40. 如何檢查對象是從哪個類創建的?

你可以使用instanceof運算符檢查對象是從哪個類創建的,同時考慮繼承。

javascript - 前端面試試題收集 - 個人文章_#vue.js_36

41. 編寫代碼,每 10 秒記錄一次在網站上花費的時間(以秒為單位)。

javascript - 前端面試試題收集 - 個人文章_#前端_37

42.什麼是純函數?

純函數需要滿足以下兩個條件的函數:

  • 每次使用相同的參數集調用該函數時,它都會返回相同的結果。
  • 它沒有副作用,這意味着它不會修改函數外部的變量。

javascript - 前端面試試題收集 - 個人文章_#javascript_38

43.什麼是高階函數?

高階函數是接受另一個函數作為參數或返回一個函數作為結果的函數。

javascript - 前端面試試題收集 - 個人文章_#javascript_39

44. 如果我們可以使用回調來處理異步代碼,為什麼還需要 Promise?

如果我們想使用回調函數從服務器異步獲取一些數據,則會導致以下結果:

javascript - 前端面試試題收集 - 個人文章_#開發語言_40

這稱為回調地獄,因為每個回調都嵌套在另一個回調中,並且每個內部回調都依賴於父函數。

使用Promises,我們可以重寫上面的代碼:

javascript - 前端面試試題收集 - 個人文章_#面試_41

有了Promises,執行順序就清晰了,讓代碼更具可讀性。

45. 編寫你自己的bind 方法的實現。

為了實現它,我們可以使用閉包和 apply() 方法將函數綁定到上下文。

javascript - 前端面試試題收集 - 個人文章_#javascript_42

46. 用加、減、乘、除和 get 方法編寫一個計算器函數。該函數必須通過可選鏈來工作。

javascript - 前端面試試題收集 - 個人文章_#前端_43

47. 編寫一個 randomSort 函數,該函數接受一個數字數組並按隨機順序對數組進行排序。

你可以使用 sort() 方法和 Math.random() 來實現此目的。

javascript - 前端面試試題收集 - 個人文章_#javascript_44

48. 編寫一個deleteGreatestValue 函數,該函數接受一個二維數字數組,並從每個嵌套數組中刪除最大的數字。

我們應該迭代每個嵌套數組,獲取每個嵌套數組的最大值並將其刪除。

javascript - 前端面試試題收集 - 個人文章_#開發語言_45

49. 編寫一個 sortPeople 函數,它接受一個字符串名稱數組和一個數字高度數組,其中名稱[i] == heights[i]。它應該根據高度數組對名稱數組進行排序。

javascript - 前端面試試題收集 - 個人文章_#javascript_46

50. 編寫一個subsets 函數,它接受一個數字數組nums 並返回這些數字的所有可能的數組變體。

javascript - 前端面試試題收集 - 個人文章_#javascript_47

51.如何反轉鏈表?

讓我們創建一個函數reverseLinkedList,它將鏈表作為輸入並返回該列表的反轉版本。

方法:

  • 它用 null 初始化結果變量,該變量將保存反轉的列表。
  • 它使用 head 初始化 root 變量,該變量指向列表的開頭。
  • 它進入一個 while 循環,一直持續到 root 變為 null,表示列表末尾。
  • 在循環內部,它檢查結果是否已經有元素。如果是,它會使用當前值 root.val 和指向下一個節點結果的指針創建一個新的列表節點。然後它用這個新節點更新結果。
  • 如果 result 還沒有任何元素,它將創建一個新的列表節點,其中當前值 root.val 和 null 作為指向下一個節點的指針。然後它用這個新節點更新結果。
  • 更新結果後,通過將 root.next 分配給 root 來移動到列表中的下一個元素。
  • while 循環完成後,它返回結果中存儲的反轉列表。

總之,該函數通過從頭到尾迭代每個節點,為每個值創建一個新的列表節點並相應地更新指針來反轉鏈表。

javascript - 前端面試試題收集 - 個人文章_#vue.js_48

52.如何對鏈表進行排序?

讓我們創建一個函數 sortList,它將鏈表作為輸入並返回該列表的排序版本。

方法:

  • 檢查給定的鏈表是否為空。
  • 遍歷鏈表並將節點值存儲到數組中。
  • 使用內置的 sort() 方法對數組進行排序。
  • 使用排序後的數組創建一個新的鏈表。
  • 返回創建的鏈表的頭。

javascript - 前端面試試題收集 - 個人文章_#javascript_49

53. Observables 和 Promise 之間有什麼區別?

Observables 和 Promises 都用於處理 JavaScript 中的異步操作。

一個關鍵的區別是 Observables 可以隨着時間的推移發出多個值。

它們適合處理數據流,例如用户交互、事件或來自 API 的隨時間變化的數據。另一方面,承諾只能用單個值解析一次。

它們適合處理要麼成功要麼失敗的單個異步操作。

總之,Promises 最適合處理具有單個結果的一次性異步操作,而 Observables 在處理持續的數據流、事件和複雜的數據處理管道時更強大。