
1. JavaScript 核心知識體系與面試準備指南作為一名經歷過數十場技術面試的前端工程師我深知JavaScript基礎知識在面試中的重要性。很多看似簡單的概念在實際工作中卻經常成為性能瓶頸和bug源頭。本文將系統梳理JavaScript的核心知識體系幫助開發者建立完整的知識框架同時針對面試場景提供深度解析。JavaScript作為一門靈活多變的語言其核心機制往往隱藏在簡單的語法背后。理解這些機制不僅能讓你在面試中游刃有余更能提升日常開發中的問題解決能力。我們將從基礎數據類型開始逐步深入到異步編程等高級主題每個部分都會結合實際面試題進行剖析。2. 基礎數據類型與類型判斷2.1 JavaScript的71種數據類型JavaScript中的數據類型可以分為兩大類原始類型和對象類型。具體包括原始類型Undefined、Null、Boolean、Number、BigInt、String、Symbol對象類型Object包括Array、Function等特殊對象注意typeof null會返回object這是JavaScript早期實現的一個著名bug由于兼容性原因一直保留至今2.2 類型判斷的四種方法typeof操作符typeof 42 // number typeof hello // string typeof undefined // undefined typeof true // boolean typeof Symbol() // symbol typeof {} // object typeof [] // object (注意數組也是object) typeof function(){} // functioninstanceof操作符 用于檢測構造函數的prototype屬性是否出現在對象的原型鏈上[] instanceof Array // true new Date() instanceof Date // trueObject.prototype.toString 最可靠的類型判斷方法Object.prototype.toString.call([]) // [object Array] Object.prototype.toString.call(null) // [object Null]Array.isArray() 專門用于判斷數組類型Array.isArray([]) // true Array.isArray({}) // false2.3 類型轉換的陷阱面試中經常考察和的區別1 1 // true (類型轉換后比較) 1 1 // false (嚴格比較不轉換類型) 0 false // true 0 false // false null undefined // true null undefined // false3. 變量、作用域與閉包3.1 var、let和const的區別特性varletconst作用域函數作用域塊級作用域塊級作用域變量提升是否否重復聲明允許不允許不允許初始值可不設可不設必須設置重新賦值允許允許不允許3.2 作用域鏈與閉包閉包是指有權訪問另一個函數作用域中的變量的函數。理解閉包需要掌握詞法作用域函數在定義時就確定了作用域而非執行時執行上下文包含變量對象、作用域鏈和this值垃圾回收閉包會阻止被引用的變量被回收經典面試題for(var i 0; i 5; i) { setTimeout(function() { console.log(i); }, 1000); } // 輸出五個5如何修改使其輸出0-4解決方案// 使用let for(let i 0; i 5; i) { setTimeout(function() { console.log(i); }, 1000); } // 或使用IIFE for(var i 0; i 5; i) { (function(j) { setTimeout(function() { console.log(j); }, 1000); })(i); }4. 數組操作與性能考量4.1 數組方法分類變異方法會改變原數組push/pop/shift/unshiftsplice/sort/reversefill/copyWithin非變異方法返回新數組slice/concatmap/filter/reduceflat/flatMap4.2 數組遍歷性能對比方法速度可中斷適用場景for循環最快是需要高性能的場景forEach中等否簡單遍歷for...of慢是需要可讀性的場景map/filter慢否需要返回新數組的場景4.3 數組去重的幾種方式// 使用Set const unique arr [...new Set(arr)]; // 使用filter const unique arr arr.filter((item, index) arr.indexOf(item) index); // 使用reduce const unique arr arr.reduce((acc, cur) acc.includes(cur) ? acc : [...acc, cur], []);5. 函數進階與this指向5.1 箭頭函數與普通函數區別特性普通函數箭頭函數this綁定動態綁定詞法綁定arguments有無構造函數可以不可以prototype有無yield可用不可用5.2 this指向的四種規則默認綁定非嚴格模式下指向window嚴格模式為undefined隱式綁定作為對象方法調用時指向該對象顯式綁定通過call/apply/bind指定thisnew綁定構造函數中的this指向新創建的對象5.3 手寫call/apply/bind// call實現 Function.prototype.myCall function(context, ...args) { context context || window; const fn Symbol(); context[fn] this; const result context[fn](...args); delete context[fn]; return result; }; // bind實現 Function.prototype.myBind function(context, ...args) { const self this; return function(...innerArgs) { return self.apply(context, args.concat(innerArgs)); }; };6. 對象與原型系統6.1 原型鏈示意圖實例對象.__proto__ → 構造函數.prototype → Object.prototype → null6.2 繼承的幾種方式原型鏈繼承function Parent() {} function Child() {} Child.prototype new Parent();構造函數繼承function Child() { Parent.call(this); }組合繼承最常用function Child() { Parent.call(this); } Child.prototype Object.create(Parent.prototype); Child.prototype.constructor Child;ES6 class繼承class Child extends Parent { constructor() { super(); } }6.3 深拷貝的實現function deepClone(obj, map new WeakMap()) { if (obj null || typeof obj ! object) return obj; if (map.has(obj)) return map.get(obj); const clone Array.isArray(obj) ? [] : {}; map.set(obj, clone); for (const key in obj) { if (obj.hasOwnProperty(key)) { clone[key] deepClone(obj[key], map); } } return clone; }7. 異步編程模型7.1 事件循環機制JavaScript的事件循環執行順序執行同步代碼執行所有微任務Promise.then, process.nextTick執行一個宏任務setTimeout, setInterval, I/O重復2-3步驟7.2 Promise核心實現class MyPromise { constructor(executor) { this.state pending; this.value undefined; this.reason undefined; this.onFulfilledCallbacks []; this.onRejectedCallbacks []; const resolve value { if (this.state pending) { this.state fulfilled; this.value value; this.onFulfilledCallbacks.forEach(fn fn()); } }; const reject reason { if (this.state pending) { this.state rejected; this.reason reason; this.onRejectedCallbacks.forEach(fn fn()); } }; try { executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled, onRejected) { return new MyPromise((resolve, reject) { const handleFulfilled () { try { const x onFulfilled(this.value); x instanceof MyPromise ? x.then(resolve, reject) : resolve(x); } catch (err) { reject(err); } }; const handleRejected () { try { const x onRejected(this.reason); x instanceof MyPromise ? x.then(resolve, reject) : resolve(x); } catch (err) { reject(err); } }; if (this.state fulfilled) { handleFulfilled(); } else if (this.state rejected) { handleRejected(); } else { this.onFulfilledCallbacks.push(handleFulfilled); this.onRejectedCallbacks.push(handleRejected); } }); } }7.3 async/await原理async函數本質上是Generator函數的語法糖其執行過程遇到await時會暫停async函數的執行等待Promise解決后繼續執行async函數如果Promise被拒絕會拋出異常// async/await轉換為Promise形式 async function example() { const result await somePromise(); return result 1; } // 等價于 function example() { return somePromise().then(result { return result 1; }); }8. 面試實戰技巧與高頻問題8.1 高頻面試問題整理閉包應用場景模塊模式函數柯里化記憶化函數事件處理回調原型鏈相關問題如何實現繼承instanceof原理是什么new操作符做了什么異步編程問題事件循環執行順序Promise.all/Promise.race實現如何取消Promise8.2 代碼輸出題解析console.log(1); setTimeout(() { console.log(2); Promise.resolve().then(() console.log(3)); }, 0); new Promise((resolve) { console.log(4); resolve(); }).then(() { console.log(5); setTimeout(() console.log(6), 0); }); console.log(7); // 輸出順序1, 4, 7, 5, 2, 3, 68.3 手寫代碼準備清單實現Promise及相關靜態方法實現call/apply/bind實現深拷貝實現防抖節流實現觀察者模式實現數組扁平化實現函數柯里化在實際面試中理解概念背后的原理比死記硬背更重要。建議對每個知識點都嘗試自己實現一遍遇到問題時多思考為什么這樣設計。JavaScript的很多特性都有其歷史原因和實際考量理解這些背景能讓你在面試中給出更有深度的回答。