天天看點

174道 JavaScript 面試題,助你查漏補缺

最近在整理 JavaScript 的時候發現遇到了很多面試中常見的面試題,本部分主要是作者在 Github 等各大論壇收錄的 JavaScript 相關知識和一些相關面試題時所做的筆記,分享這份總結給大家,對大家對 JavaScript 的可以來一次全方位的檢漏和排查,感謝原作者 CavsZhouyou 的付出,原文連結放在文章最下方,如果出現錯誤,希望大家共同指出!

附筆記連結,閱讀往期更多優質文章可移步檢視,喜歡的可以給我點贊鼓勵哦:https://github.com/Wscats/articles

涉及知識點:

棧:原始資料類型(Undefined、Null、Boolean、Number、String)

堆:引用資料類型(對象、數組和函數)

回答:

詳細資料可以參考:

《JavaScript 有幾種類型的值?》

《JavaScript 有幾種類型的值?能否畫一下它們的記憶體圖;》

《什麼是堆?什麼是棧?他們之間有什麼差別和聯系?》

《标準内置對象的分類》

《JS 所有内置對象屬性和方法彙總》

《JavaScript 深入了解之 undefined 與 null》

《JavaScript 深入了解之原型與原型鍊》

p.proto

p.constructor.prototype

Object.getPrototypeOf(p)

以 0X、0x 開頭的表示為十六進制。

以 0、0O、0o 開頭的表示為八進制。

以 0B、0b 開頭的表示為二進制格式。

《JavaScript 字元串間的比較》

《詳解 JS 中 Number()、parseInt() 和 parseFloat() 的差別》

《前端表單驗證常用的 15 個 JS 正規表達式》

《JS 常用正則彙總》

《JS - 生成随機數的方法彙總(不同範圍、類型的随機數)》

《Fisher and Yates 的原始版》

《javascript 實作數組随機排序?》

《JavaScript 學習筆記:數組随機排序》

《JavaScript 深入了解之對象建立》

《JavaScript 深入了解之繼承》

《JavaScript 深入了解之作用域鍊》

1.第一種是函數調用模式,當一個函數不是一個對象的屬性時,直接作為函數來調用時,this 指向全局對象。

2.第二種是方法調用模式,如果一個函數作為一個對象的方法來調用時,this 指向這個對象。

3.第三種是構造器調用模式,如果一個函數用 new 調用時,函數執行前會新建立一個對象,this 指向這個新建立的對象。

4.第四種是 apply 、 call 和 bind 調用模式,這三個方法都可以顯示的指定調用函數的 this 指向。其中 apply 方法接收兩個參數:一個是 this 綁定的對象,一個是參數數組。call 方法接收的參數,第一個是 this 綁定的對象,後面的其餘參數是傳入函數執行的參數。也就是說,在使用 call() 方法時,傳遞給函數的參數必須逐個列舉出來。bind 方法通過傳入一個對象,傳回一個 this 綁定了傳入對象的新函數。這個函數的 this 指向除了使用 new 時會被改變,其他情況下都不會改變。

《JavaScript 深入了解之 this 詳解》

《eval()》

《DOM, DOCUMENT, BOM, WINDOW 有什麼差別?》

《Window 對象》

《DOM 與 BOM 分别是什麼,有何關聯?》

《JavaScript 學習總結(三)BOM 和 DOM 詳解》

《JS 事件模型》

1.事件是使用者操作網頁時發生的互動動作,比如 click/move, 事件除了使用者觸發的動作外,還可以是文檔加載,視窗滾動和大小調整。事件被封裝成一個 event 對象,包含了該事件發生時的所有相關資訊( event 的屬性)以及可以對事件進行的操作( event 的方法)。

2.事件處理機制:IE 支援事件冒泡、Firefox 同時支援兩種事件模型,也就是:事件冒泡和事件捕獲。

3.event.stopPropagation() 或者 ie 下的方法 event.cancelBubble = true;

《Javascript 事件模型系列(一)事件及事件的三種模型》

《Javascript 事件模型:事件捕獲和事件冒泡》

《一個 DOM 元素綁定多個事件時,先執行冒泡還是捕獲》

《JavaScript 事件委托詳解》

《為什麼 ["1", "2", "3"].map(parseInt) 傳回 [1,NaN,NaN]?》

《JavaScript 深入了解之閉包》

相關知識點:

消除 Javascript 文法的一些不合理、不嚴謹之處,減少一些怪異行為;

消除代碼運作的一些不安全之處,保證代碼運作的安全;

提高編譯器效率,增加運作速度;

為未來新版本的 Javascript 做好鋪墊。

差別:

1.禁止使用 with 語句。

2.禁止 this 關鍵字指向全局對象。

3.對象不能有重名的屬性。

《Javascript 嚴格模式詳解》

《js 判斷一個對象是否屬于某一類》

《instanceof》

《new 操作符具體幹了什麼?》

《JavaScript 深入之 new 的模拟實作》

《Object.prototype.hasOwnProperty()》

《深入了解 JavaScript 中的 JSON 》

《通過一行代碼學 JavaScript》

一般有以下幾種方式:

defer 屬性

async 屬性

動态建立 DOM 方式

使用 setTimeout 延遲方法

讓 JS 最後加載

《JS 延遲加載的幾種方式》

《HTML 5 <code>&lt;script&gt;</code> <code>async</code> 屬性》

2005 年 2 月,AJAX 這個詞第一次正式提出,它是 Asynchronous JavaScript and XML 的縮寫,指的是通過 JavaScript 的

異步通信,從伺服器擷取 XML 文檔從中提取資料,再更新目前網頁的對應部分,而不用重新整理整個網頁。

具體來說,AJAX 包括以下幾個步驟。

1.建立 XMLHttpRequest 對象,也就是建立一個異步調用對象

2.建立一個新的 HTTP 請求,并指定該 HTTP 請求的方法、URL 及驗證資訊

3.設定響應 HTTP 請求狀态變化的函數

4.發送 HTTP 請求

5.擷取異步調用傳回的資料

6.使用 JavaScript 和 DOM 實作局部重新整理

一般實作:

《XMLHttpRequest 對象》

《從 ajax 到 fetch、axios》

《Fetch 入門》

《傳統 Ajax 已死,Fetch 永生》

《淺談浏覽器緩存》

《前端優化:浏覽器緩存技術介紹》

《請求頭中的 Cache-Control》

《Cache-Control 字段值詳解》

1.在 ajax 發送請求前加上 anyAjaxObj.setRequestHeader("If-Modified-Since","0")。

2.在 ajax 發送請求前加上 anyAjaxObj.setRequestHeader("Cache-Control","no-cache")。

3.在 URL 後面加上一個随機數: "fresh=" + Math.random();。

4.在 URL 後面加上時間戳:"nowtime=" + new Date().getTime();。

5.如果是使用 jQuery,直接這樣就可以了$.ajaxSetup({cache:false})。這樣頁面的所有 ajax 都會執行這條語句就是不需要儲存緩存記錄。

《Ajax 中浏覽器的緩存問題解決方法》

《同步和異步的差別》

1.通過 jsonp 跨域

2.document.domain + iframe 跨域

3.location.hash + iframe

4.window.name + iframe 跨域

5.postMessage 跨域

6.跨域資源共享(CORS)

7.nginx 代理跨域

8.nodejs 中間件代理跨域

9.WebSocket 協定跨域

《前端常見跨域解決方案(全)》

《浏覽器同源政策及其規避方法》

《跨域,你需要知道的全在這裡》

《為什麼 form 表單送出沒有跨域問題,但 ajax 送出有跨域問題?》

《深入淺出 Nginx》

《HTTP cookies》

《聊一聊 cookie》

《淺談子產品化開發》

《Javascript 子產品化程式設計(一):子產品的寫法》

《前端子產品化:CommonJS,AMD,CMD,ES6》

《Module 的文法》

它們之間的主要差別有兩個方面。

(1)第一個方面是在子產品定義時對依賴的處理不同。AMD 推崇依賴前置,在定義子產品的時候就要聲明其依賴的子產品。而 CMD 推崇

就近依賴,隻有在用到某個子產品的時候再去 require。

(2)第二個方面是對依賴子產品的執行時機處理不同。首先 AMD 和 CMD 對于子產品的加載方式都是異步加載,不過它們的差別在于

子產品的執行時機,AMD 在依賴子產品加載完成後就直接執行依賴子產品,依賴子產品的執行順序和我們書寫的順序不一定一緻。而 CMD

在依賴子產品加載完成後并不執行,隻是下載下傳而已,等到所有的依賴子產品都加載好後,進入回調函數邏輯,遇到 require 語句

的時候才執行對應的子產品,這樣子產品的執行順序就和我們書寫的順序保持一緻了。

《前端子產品化,AMD 與 CMD 的差別》

1.CommonJS 子產品輸出的是一個值的拷貝,ES6 子產品輸出的是值的引用。CommonJS 子產品輸出的是值的拷貝,也就是說,一旦輸出一個值,子產品内部的變化就影響不到這個值。ES6 子產品的運作機制與 CommonJS 不一樣。JS 引擎對腳本靜态分析的時候,遇到子產品加載指令 import,就會生成一個隻讀引用。等到腳本真正執行時,再根據這個隻讀引用,到被加載的那個子產品裡面去取值。

2.CommonJS 子產品是運作時加載,ES6 子產品是編譯時輸出接口。CommonJS 子產品就是對象,即在輸入時是先加載整個子產品,生成一個對象,然後再從這個對象上面讀取方法,這種加載稱為“運作時加載”。而 ES6 子產品不是對象,它的對外接口隻是一種靜态定義,在代碼靜态解析階段就會生成。

《requireJS 的用法和原理分析》

《requireJS 的核心原理是什麼?》

《從 RequireJs 源碼剖析腳本加載原理》

《requireJS 原理分析》

《JS 子產品加載器加載原理是怎麼樣的?》

《ECMAScript 6 實作了 class,對 JavaScript 前端開發有什麼意義?》

《Class 的基本文法》

《簡述 document.write 和 innerHTML 的差別。》

(1)建立新節點

(2)添加、移除、替換、插入

(3)查找

(4)屬性操作

《DOM 概述》

《原生 JavaScript 的 DOM 操作彙總》

《原生 JS 中 DOM 節點相關 API 合集》

《apply、call 的差別和用途》

常見的類數組轉換為數組的方法有這樣幾種:

(1)通過 call 調用數組的 slice 方法來實作轉換

(2)通過 call 調用數組的 splice 方法來實作轉換

(3)通過 apply 調用數組的 concat 方法來實作轉換

(4)通過 Array.from 方法來實作轉換

詳細的資料可以參考:

《JavaScript 深入之類數組對象與 arguments》

《javascript 類數組》

《深入了解 JavaScript 類數組》

《JavaScript 深入了解之 Array 類型詳解》

《Array.prototype.fill()》

《尾後逗号》

《JavaScript 深入了解之變量對象》

1.使用位運算代替一些簡單的四則運算。

2.避免使用過深的嵌套循環。

3.不要使用未定義的變量。

4.當需要多次通路數組長度時,可以用變量儲存起來,避免每次都會去進行屬性查找。

《如何編寫高性能的 Javascript?》

《深入了解 V8 的垃圾回收原理》

《JavaScript 中的垃圾回收》

1.意外的全局變量

2.被遺忘的計時器或回調函數

3.脫離 DOM 的引用

4.閉包

《JavaScript 記憶體洩漏教程》

《4 類 JavaScript 記憶體洩漏及如何避免》

《杜絕 js 中四種記憶體洩漏類型的發生》

《javascript 典型記憶體洩漏及 chrome 的排查方法》

《pushState + ajax 實作浏覽器無重新整理前進後退》

《Manipulating the browser history》

《為什麼把 script 标簽放在 body 結束标簽之後 html 結束标簽之前?》

《從 Chrome 源碼看浏覽器如何加載資源》

有三種辦法來解決這個問題:

1.通過 meta 标簽禁用網頁的縮放。

2.通過 meta 标簽将網頁的 viewport 設定為 ideal viewport。

3.調用一些 js 庫,比如 FastClick

《移動端 300ms 點選延遲和點選穿透》

《什麼是“前端路由”》

《淺談前端路由》

《前端路由是什麼東西?》

《淺談前端單元測試》

《JavaScript 判斷浏覽器類型》

《Web 開發中的“黑話”》

《Polyfill 為何物》

《如何更有效的擷取檔案擴充名》

《輕松了解 JS 函數節流和函數防抖》

《JavaScript 事件節流和事件防抖》

《JS 的防抖與節流》

《escape,encodeURI,encodeURIComponent 有什麼差別?》

《字元編碼詳解》

《字元編碼筆記:ASCII,Unicode 和 UTF-8》

《浏覽器事件循環機制(event loop)》

《詳解 JavaScript 中的 Event Loop(事件循環)機制》

《什麼是 Event Loop?》

《這一次,徹底弄懂 JavaScript 執行機制》

相關資料:

《JavaScript 專題之深淺拷貝》

《前端面試之道》

call 函數的實作步驟:

1.判斷調用對象是否為函數,即使我們是定義在函數的原型上的,但是可能出現使用 call 等方式調用的情況。

2.判斷傳入上下文對象是否存在,如果不存在,則設定為 window 。

3.處理傳入的參數,截取第一個參數後的所有參數。

4.将函數作為上下文對象的一個屬性。

5.使用上下文對象來調用這個方法,并儲存傳回結果。

6.删除剛才新增的屬性。

7.傳回結果。

apply 函數的實作步驟:

3.将函數作為上下文對象的一個屬性。

4.判斷參數值是否傳入

4.使用上下文對象來調用這個方法,并儲存傳回結果。

5.删除剛才新增的屬性

6.傳回結果

bind 函數的實作步驟:

2.儲存目前函數的引用,擷取其餘傳入參數值。

3.建立一個函數傳回

4.函數内部使用 apply 來綁定函數調用,需要判斷函數作為構造函數的情況,這個時候需要傳入目前函數的 this 給 apply 調用,其餘情況都傳入指定的上下文對象。

《手寫 call、apply 及 bind 函數》

《JavaScript 深入之 call 和 apply 的模拟實作》

《JavaScript 專題之函數柯裡化》

《十進制的 0.1 為什麼不能用二進制很好的表示?》

《十進制浮點數轉成二進制》

《浮點數的二進制表示》

《js 浮點數存儲精度丢失原理》

《浮點數精度之謎》

《JavaScript 浮點數陷阱及解法》

《0.1+0.2 !== 0.3?》

《JavaScript 中奇特的~運算符》

《關于 2 的補碼》

《前端安全系列(一):如何防止 XSS 攻擊?》

《内容安全政策(CSP)》

《前端安全系列之二:如何防止 CSRF 攻擊?》

《[ HTTP 趣談] origin, referer 和 host 差別》

《web 安全之--點選劫持攻擊與防禦技術簡介》

《Web 安全漏洞之 SQL 注入》

《如何防範常見的 Web 攻擊》

《淺析前端開發中的 MVC/MVP/MVVM 模式》

《MVC,MVP 和 MVVM 的圖示》

《MVVM》

《一篇文章了解架構模式:MVC/MVP/MVVM》

《Vue.js 雙向綁定的實作原理》

《Object.defineProperty()》

《Virtual DOM》

《了解 Virtual DOM》

《深度剖析:如何實作一個 Virtual DOM 算法》

《網上都說操作真實 DOM 慢,但測試結果卻比 React 更快,為什麼?》

《你需要知道的 requestAnimationFrame》

《CSS3 動畫那麼強,requestAnimationFrame 還有毛線用?》

《不聊 webpack 配置,來說說它的原理》

《前端工程化——建構工具選型:grunt、gulp、webpack》

《淺入淺出 webpack》

《前端建構工具發展及其比較》

《最全的擷取元素寬高及位置的方法》

《用 Javascript 擷取頁面元素的位置》

《函數式程式設計初探》

1.HTTP 協定未規定 GET 和 POST 的長度限制

2.GET 的最大長度顯示是因為浏覽器和 web 伺服器限制了 URI 的長度

3.不同的浏覽器和 WEB 伺服器,限制的最大長度不一樣

4.要支援 IE,則最大長度為 2083byte,若隻支援 Chrome,則最大長度 8182byte

《HTTP 協定中 URI 和 URL 有什麼差別?》

《你知道 URL、URI 和 URN 三者之間的差別嗎?》

《URI、URL 和 URN 的差別》

《HTML 關于 post 和 get 的差別以及緩存問題的了解》

《懶加載和預加載》

《網頁圖檔加載優化方案》

《基于使用者行為的圖檔等資源預加載》

《mouseenter 與 mouseover 為何這般糾纏不清?》

《原生 js 實作拖拽功能基本思路》

《用 setTimeout 實作 setInterval》

《setInterval 有什麼缺點?》

1.聲明的變量隻在聲明時的代碼塊内有效

2.不存在聲明提升

3.存在暫時性死區,如果在變量聲明前使用,會報錯

4.不允許重複聲明,重複聲明會報錯

1.Symbol 函數前不能使用 new 指令,否則會報錯。

2.Symbol 函數可以接受一個字元串作為參數,表示對 Symbol 執行個體的描述,主要是為了在控制台顯示,或者轉為字元串時,比較容易區分。

3.Symbol 作為屬性名,該屬性不會出現在 for...in、for...of 循環中,也不會被 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify() 傳回。

4.Object.getOwnPropertySymbols 方法傳回一個數組,成員是目前對象的所有用作屬性名的 Symbol 值。

5.Symbol.for 接受一個字元串作為參數,然後搜尋有沒有以該參數作為名稱的 Symbol 值。如果有,就傳回這個 Symbol 值,否則就建立并傳回一個以該字元串為名稱的 Symbol 值。

6.Symbol.keyFor 方法傳回一個已登記的 Symbol 類型值的 key。

1.ES6 提供了新的資料結構 Set。它類似于數組,但是成員的值都是唯一的,沒有重複的值。

2.WeakSet 結構與 Set 類似,也是不重複的值的集合。但是 WeakSet 的成員隻能是對象,而不能是其他類型的值。WeakSet 中的對象都是弱引用,即垃圾回收機制不考慮 WeakSet 對該對象的引用,

1.Map 資料結構。它類似于對象,也是鍵值對的集合,但是“鍵”的範圍不限于字元串,各種類型的值(包括對象)都可以當作鍵。

2.WeakMap 結構與 Map 結構類似,也是用于生成鍵值對的集合。但是 WeakMap 隻接受對象作為鍵名( null 除外),不接受其他類型的值作為鍵名。而且 WeakMap 的鍵名所指向的對象,不計入垃圾回收機制。

1.将 Object 對象的一些明顯屬于語言内部的方法(比如 Object.defineProperty,放到 Reflect 對象上。

2.修改某些 Object 方法的傳回結果,讓其變得更合理。

3.讓 Object 操作都變成函數行為。

4.Reflect 對象的方法與 Proxy 對象的方法一一對應,隻要是 Proxy 對象的方法,就能在 Reflect 對象上找到對應的方法。這就讓 Proxy 對象可以友善地調用對應的 Reflect 方法,完成預設行為,作為修改行為的基礎。也就是說,不管 Proxy 怎麼修改預設行為,你總可以在 Reflect 上擷取預設行為。

《require() 源碼解讀》

《Promises/A+ 規範》

《Promise》

更多關于設計模式的資料可以參考:

《JavaScript 設計模式》

《JavaScript 中常見設計模式整理》

《觀察者模式和釋出訂閱模式有什麼不同?》

《vue 生命周期深入》

《Vue 執行個體》

《VUE 元件之間資料傳遞全集》

《做面試的不倒翁:淺談 Vue 中 computed 實作原理》

《深入了解 Vue 的 watch 實作原理及其實作方式》

《導航守衛》

《Vue 面試中,經常會被問到的面試題 Vue 知識點整理》

《Vue2.0 v-for 中 :key 到底有什麼用?》

《vue 中 key 的作用》

《混入》

《常用的幾種 Content-Type》

《JavaScript 專題之類型判斷(上)》

《js 判斷一個 object 對象是否為空》

《原生 jsonp 具體實作》

《jsonp 的原理與實作》

《前端程式員經常忽視的一個 JavaScript 面試題》

《一道考察運算符優先級的 JavaScript 面試題》

《一道常被人輕視的前端 JS 面試題》

根據上面這些屬性,可以計算出網頁加載各個階段的耗時。比如,網頁加載整個過程的耗時的計算方法如下:

《Performance API》

《ECMAScript 變量》

《JavaScript 前端倒計時糾偏實作》

1.管道通信

2.消息隊列通信

3.信号量通信

4.信号通信

5.共享記憶體通信

6.套接字通信

《程序間 8 種通信方式詳解》

《程序與線程的一個簡單解釋》

最後如果文章和筆記能帶您一絲幫助或者啟發,請不要吝啬你的贊和收藏,你的肯定是我前進的最大動力 😁

更多内容請關注:https://github.com/Wscats