JavaScript是所有現代瀏覽器 的官方語言。因此,各種語言的開發者面試中都會遇到 JavaScript 問題。
本文不講最新的 JavaScript 函式庫,通用開發實踐,或任何新的 ES6 函數 。而是講講 3 個面試中常出現的 JavaScript 問題。我問過這些問題,我的朋友說他們也問。
當然不是說你在準備JavaScript 面試時只要學習這3 個問題—— 你還有很多途徑去更好的準備即將到來的面試—— 但面試官很有可能通過下面3 個問題來判斷你了解並掌握JavaScript 和DOM 的情況。
讓我們開始吧!注意下面的範例我們使用原生 JavaScript, 因為面試官通常會想考查你在不借助函式庫(例如 jQuery)的幫助時掌握 JavaScript 和 DOM 的情況。
問題#1: 事件代理
建立應用程式時,有時需要給頁面中的按鈕,文字,或圖片新增事件監聽器,當使用者與這些元素互動時觸發某些操作。
我們以一個簡單的代辦事項清單為例,面試官會告訴你,他們希望在使用者點擊清單中某一項時觸發一個動作。並讓你用JavaScript 根據下面的HTML 程式碼實現這個功能:
<ul id="todo-app"> <li class="item">Walk the dog</li> <li class="item">Pay bills</li> <li class="item">Make dinner</li> <li class="item">Code for one hour</li> </ul>
你可能會像下面的程式碼一樣為元素添加事件監聽器:
document.addEventListener('DOMContentLoaded', function() { let app = document.getElementById('todo-app'); let items = app.getElementsByClassName('item'); // 给每个列表项添加事件监听器 for (let item of items) { item.addEventListener('click', function() { alert('you clicked on item: ' + item.innerHTML); }); } });
當然上面的程式碼能完成面試官的需求,問題是每個清單項目都會加上一個事件監聽器。當清單只有 4 項時沒有問題,但如果有人給代辦事項清單新增了 10,000 個事項呢(他們也許有一大堆事情要做)?那時函數會建立 10,000 個事件監聽器,然後把它們都加到 DOM 上。這樣 效率 非常低。
面試中最好先問一下面試官使用者最多可以新增多少個代辦事項。如果永遠不會超過 10 個,那麼上面的程式碼運行起來就沒有問題。但如果使用者輸入待辦事項的數量沒有上限,那你就得換一個更有效率的解決方案。
如果應用程式有上百個事件監聽器,更有效率的解決方案是為最外層的容器添加一個 事件監聽器,當用戶真正點擊的時候再去獲取實際被點擊的代辦事項。這稱為 事件代理 ,這比給每個代辦事項都單獨添加事件監聽器更有效率。
下面是事件代理的程式碼:
document.addEventListener('DOMContentLoaded', function() { let app = document.getElementById('todo-app'); // 给容器添加事件监听器 app.addEventListener('click', function(e) { if (e.target && e.target.nodeName === 'LI') { let item = e.target; alert('you clicked on item: ' + item.innerHTML); } }); });
問題#2: 在循環中使用閉包
面試中經常會問到閉包,因為面試官可以通過這個問題的回答判斷你對語言的熟悉程度,以及檢視你是否知道什麼時候使用閉包。
閉包就是能存取作用域外部變數的 內部函數 。閉包能用來實現 私有化 和創建 工廠函數 等作用。關於閉包的常見面試題是這樣的:
寫一個函數,循環一個整數數組,延遲3 秒列印這個數組中每個元素的索引。
這個問題常見(不正確)的實作是這樣:
const arr = [10, 12, 15, 21]; for (var i = 0; i < arr.length; i++) { setTimeout(function() { console.log('The index of this number is: ' + i); }, 3000); }
如果你執行這段函數,你會發現3 秒之後每次都印出來的是4 ,而不是預期的0, 1, 2, 3 。
為了正確的找到出現這種情況的原因,你需要理解 JavaScript 是如何運行這段程式碼的,這也是面試官想要考察你的地方。
原因是 setTimeout 函數建立了一個存取外部作用域的函數(閉包),就是包含索引 i 的那個循環。 3 秒之後,函數開始執行列印 i 的值,而此時循環也結束了, i 的值已經是 4。因為循環遍歷 0, 1, 2, 3, 4 後最終停在了 4。
其實有 好幾種方法 能 正確 解決這個問題。這裡有兩個:
const arr = [10, 12, 15, 21]; for (var i = 0; i < arr.length; i++) { // 给每个函数传入变量 i 让其能访问正确的索引 setTimeout(function(i_local) { return function() { console.log('The index of this number is: ' + i_local); } }(i), 3000); }
const arr = [10, 12, 15, 21]; for (let i = 0; i < arr.length; i++) { // 使用 ES6 中的 let 关键字,它会在函数调用时创建一个新的绑定 // 了解更多:http://exploringjs.com/es6/ch_variables.html#sec_let-const-loop-heads setTimeout(function() { console.log('The index of this number is: ' + i); }, 3000); }
問題#3: Debouncing(防抖動)
有些瀏覽器事件能在很短的時間內被觸發多次,例如調整視窗大小或捲動頁面。如果你為視窗滾動事件新增一個事件監聽器,然後使用者不停地快速向下捲動頁面,那你的事件可能在 3 秒之內被觸發數千次。這會導致非常嚴重的效能問題。
如果在面試中討論到構建應用程序,以及滾動事件,窗口調整事件,或者鍵盤事件等,請務必提及 debouncing 或者 throttling,作為提高頁面速度與性能的方法。來一個 css-tricks 的實例:
2011 年,Twitter 出了一個問題:當滾動 Twitter 摘要時,頁面變的很卡甚至沒有回應。 John Resig 寫了 一篇關於這個問題的部落格 ,解釋了直接將耗時的函數綁定在 scroll 事件上是一個多麼糟糕的想法。
Debouncing 是解决这个问题的一种方法,它的做法是限制下次函数调用之前必须等待的时间间隔。正确实现 debouncing 的方法是将若干个函数调用 合成 一次,并在给定时间过去之后仅被调用一次。下面是一个原生 JavaScript 的实现,用到了 作用域 , 闭包, this , 和 计时事件 :
// 将会包装事件的 debounce 函数 function debounce(fn, delay) { // 维护一个 timer let timer = null; // 能访问 timer 的闭包 return function() { // 通过 ‘this’ 和 ‘arguments’ 获取函数的作用域和变量 let context = this; let args = arguments; // 如果事件被调用,清除 timer 然后重新设置 timer clearTimeout(timer); timer = setTimeout(function() { fn.apply(context, args); }, delay); } }
这个函数 — 当传入一个事件(fn)时 — 会在经过给定的时间(delay)后执行。
函数这样用:
// 当用户滚动时被调用的函数 function foo() { console.log('You are scrolling!'); } // 在 debounce 中包装我们的函数,过 2 秒触发一次 let elem = document.getElementById('container'); elem.addEventListener('scroll', debounce(foo, 2000));
Throttling 是与 debouncing 类似的一种技术,但它不是在调用函数之前等待一段时间,throttling 是在较长的时间间隔内调用函数。所以如果一个事件每 100 毫秒被触发 10 次,throttling 会在每隔 2 秒时执行一次这个函数,而不是在 100 毫秒内执行 10 次事件。
以上是3 個 JavaScript面試需要注意的問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

Atom編輯器mac版下載
最受歡迎的的開源編輯器

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

禪工作室 13.0.1
強大的PHP整合開發環境

WebStorm Mac版
好用的JavaScript開發工具