日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

2022 前端一场面试及答案整理

發布時間:2023/12/20 HTML 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2022 前端一场面试及答案整理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

金三馬上就要開始了,俗話說得好,知己知彼百戰百勝,多準備總是沒有錯的。以面試的形式和大家一起學習、一起回顧我們的職場生涯。今天簡單總結一下我個人去面試,包括我在面試別人時的經驗。加油加加油!!!

目錄

開頭熱場問題

1. 說一下工作中解決過比較困難的問題 或 說一下自己項目中比較有亮點的地方

2. 你了解瀏覽器的事件循環嗎?

? ? 2.1 為什么 js 在瀏覽器中有事件循環的機制?

? ? 2.2 你了解事件循環當中的兩種任務嗎?

? ? 2.3 為什么要引入微任務的概念,只有宏任務可以嗎?

? ? 2.4 你了解 Node.js 的事件循環嗎?Node中的事件循環和瀏覽器的事件循環有什么區別?

? ? ? ? 2.5 這個時候理論問了這么多了,開始實踐1

? ? ? ? 2.6 實踐2

? ? ?2.7 實踐3?

3. 事件的捕獲和冒泡機制你了解多少?

? ? 3.1 基本概念

? ? 3.2? window.addEventListener 監聽的是什么階段的事件?? ? ? ? ?

? ? 3.3 平常有哪些場景用到了這些機制??

4.? 你工作中用過防抖和節流嗎?

? ? 4.1 基本概念

? ? 4.2 分別適合用在什么場景?

? ? 4.3? 手寫節流函數

5. 你了解 Promise 嗎?平時用的多嗎?

? ? 5.1 Promise.all( ) 你知道有什么特性嗎?

? ? 5.2?如果其中一個 Promise 報錯了怎么辦?

? ? 5.3?如果有一個 Promise 報錯了,那么其他的 Promise 還會執行嗎?

? ? 5.4 手寫一個?Promise.all(? )

? ? 5.5 Promise 在初始化的時候已經執行了,那么利用這個特性我們可以做點什么(擴展性問題)?

?6. 字節經典算法題---- 接雨水


開頭熱場問題

1. 說一下工作中解決過比較困難的問題 或 說一下自己項目中比較有亮點的地方

考察目的:面試官主要看一下我們解決問題的能力

解答:這個問題 主要是靠大家的工作積累,平時工作過程中可以養成一個良好的習慣,無論做什么需求的時候,都花點時間去記錄一下,這樣積累無論是一年,還是兩年,或者五年都會積累很多也無需求,然后自己梳理一下,在面試的時候反饋給面試官,讓面試官虎軀一震,offer馬上到手~~~

2. 你了解瀏覽器的事件循環嗎?

考察目的:以此問題作為一個突破口,深度挖掘你對整個概念的了解

2.1 為什么 js 在瀏覽器中有事件循環的機制?

解答

① JS 是單線程的

② event loop

2.2 你了解事件循環當中的兩種任務嗎?

解答

① 宏任務:整體代碼塊、setTimeOut、setInterval、I/O操作

② 微任務:new Promise().then()、mutationObserver(前端的回溯)

2.3 為什么要引入微任務的概念,只有宏任務可以嗎?

解答

宏任務:先進先出的原則

在 JS 的執行過程中 或者說在頁面的渲染過程中,宏任務是按照先進先出的原則執行,我們并不能準確的控制 這些任務被推進任務隊列里,但是我們這個時候如果出來一個非常高優先級的任務,這個時候該怎么辦?如果我們只有宏任務,再往任務隊列里面推一個,秉承著先進先出的原則,那么它肯定是最后一個執行的,所以要引入微任務;

了解到宏任務與微任務過后,我們來學習宏任務與微任務的執行順序。

  • 代碼開始執行,創建一個全局調用棧,script作為宏任務執行
  • 執行過程過同步任務立即執行,異步任務根據異步任務類型分別注冊到微任務隊列和宏任務隊列
  • 同步任務執行完畢,查看任務隊列
    • 若存在微任務,將微任務隊列全部執行(包括執行微任務過程中產生的新微任務)
    • 若無微任務,查看宏任務隊列,執行第一個宏任務,宏任務執行完畢,查看微任務隊列,重復上述操作,直至宏任務隊列為空

2.4 你了解 Node.js 的事件循環嗎?Node中的事件循環和瀏覽器的事件循環有什么區別?

解答

Node宏任務的執行順序:

① timers定時器:執行已經安排過的,setTimeout 和 setInterval 的回調函數;

②pending callback 待定回調:執行延遲到下一個循環迭代的I/O回調;

③idle,prepare:僅系統內部使用;

④poll:檢索新的I/O事件,執行與I/O相關的回調

⑤check:執行setImmediate() 回調函數

⑥close callback:socket.on(‘close’, ( )=>{ })

微任務和宏任務在node的執行順序:

首先大家要明白,Node中微任務和宏任務的執行順序是和 node 的版本有關系的

Node V10 之前:

① 執行完上述一個階段中的所有任務

② 執行 nextTick 隊列里面的內容

③ 執行完微任務隊列的內容

Node V10 之后:

和瀏覽器的行為統一了

2.5 這個時候理論問了這么多了,開始實踐1

async function async1() {console.log("async1 start");await async2();console.log("async1 end"); } async function async2() {console.log("async2"); } console.log("script start"); setTimeout(() => {console.log("setTimeout"); }, 0); async1(); new Promise((resolve) => {console.log("promise1");resolve(); }).then(() => {console.log("promise2"); }); console.log("script end");// 1. script start // 2. async1 start // 3. async2 // 4. promise1 // 5. script end // 6. async1 end // 7. promise2 // 8. setTimeout

2.6 實踐2

這個就比較有難度了,如果真的不會,千萬不要張嘴就來一句:“我不會”,這個時候我作為面試官的時候心里就在想:“我屮艸芔茻,這好尷尬”!娛樂一下開個玩笑,這個時候要嘗試著說出自己的思路,即使是錯的,你也要讓面試官看到你的 進取、鉆研精神!

console.log("start"); setTimeout(() => {console.log("children2");Promise.resolve().then(() => {console.log("children3");}); }, 0);new Promise((resolve, reject) => {console.log("children4");setTimeout(() => {console.log("children5");resolve("children6"); // 此處大坑}, 0); }).then((res) => {console.log("children7");setTimeout(() => {console.log(res);}, 0); });// 1. start // 2. children4 /** 第一輪宏任務執行結束,嘗試清空微任務隊列,發現沒有微任務,嘗試執行下一輪宏任務 */ // 3. children2 /** 第二輪宏任務執行結束,嘗試清空微任務隊列, */ // 4. children3 // 5. children5 /** 第三輪宏任務執行結束,嘗試清空微任務隊列, */ // 6. children7 // 7. children6

2.7 實踐3

到這一步,大家心里是不是在想:“面試官怎么抓著 事件循環不放了”,最后一道題

const p = () => {return new Promise((resolve, reject) => {const p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve(1); // 這里 不會再輸出了,因為 resolve(2) 已經把結果輸出}, 0);resolve(2);});p1.then((res) => {console.log(res);});console.log(3);resolve(4);}); }; p().then((res) => {console.log(res); }); console.log("end");// 1. 3 // 2. end // 3. 2 // 4. 4

到此為止,事件循環結束!

3. 事件的捕獲和冒泡機制你了解多少?

3.1 基本概念

以HTML為例:↓

捕獲:從window → parent → child → son 到目標元素以后,轉為冒泡

冒泡:目標元素 son→ child→ parent→window

3.2 window.addEventListener 監聽的是什么階段的事件?

// 冒泡階段 window.addEventListener("click", () => {}); // 第三個參數默認為 false,為false 時,監聽的為冒泡階段// 捕獲階段 window.addEventListener("click", () => {}, true);

3.3 平常有哪些場景用到了這些機制?

3.3.1. 事件委托

<ul id="ul"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>const ul = document.querySelector("ul");ul.addEventListener("click", (e) => {const target = e.target;if (target.tagName.toLowerCase() === "li") {const liList = document.querySelectorAll("li");// 這里之所以會這么寫,是因為 liList 并非是一個真正的 Array// 此時返回的是一個 nodeList,如果想使用 數組的 方法,需要改變thisconst index = Array.prototype.indexOf.call(liList, target);console.log(`內容:${target.innerHTML},索引:${index}`);}});

3.3.2 場景設計題

一個歷史頁面,上面有若干按鈕的點擊邏輯,每個按鈕都有自己的 click 事件

新需求來了:給每一個訪問的用戶添加了一個屬性,如果 banned = true,此用戶點擊頁面上的任何按鈕或元素,都不可響應原來的函數。而是直接 alert 提示,你被封禁了。

實現:采用 事件捕獲 機制完成(當然實現的思路有三種,甚至更多,這里只說事件捕獲)

/*** 場景設計題 ????一個歷史頁面,上面有若干按鈕的點擊邏輯,每個按鈕都有自己的 click 事件 ? ? ?新需求來了:給每一個訪問的用戶添加了一個屬性,如果 banned = true,此用戶點擊頁面上的任何按鈕或元素,都不可響應原來的函數。而是直接 alert 提示,你被封禁了。 */window.addEventListener("click",(e) => {if (banned) {e.stopPropagation();}},true );

4. 你工作中用過防抖和節流嗎?

4.1 基本概念

防抖:持續觸發事件的時候,一定時間段內,沒有再觸發事件,時間處理函數才會執行一次

節流:持續觸發事件的時候,保證一段時間內只調用一次事件處理函數(固定時間)

4.2 分別適合用在什么場景?

防抖:input輸入(巨量引擎)

節流:resize(屏幕大小改變)、scroll(滾動時) —> 一定要執行的,給一個固定間隔

4.3 手寫節流函數

時間戳寫法,第一次立即執行

// 時間戳寫法,第一次立即執行 const throttle = (fn, interval) => {let last = 0;return () => {let now = Date.now();if (now - last >= interval) {fn.apply(this, arguments);}}; }; const handle = () => {console.log(Math.random()); }; const throttleHandle = throttle(handle, 3000); throttleHandle(); throttleHandle();

定時器寫法,第一次也需要延時 具體 時間以后再執行

// 定時器寫法,第一次也會延時 具體的時間執行 const throttle = (fn, interval) => {let timer = null;return function () {let context = this;let args = arguments;if (!timer) {timer = setTimeout(() => {fn.apply(context, args);timer = null;}, interval);}}; }; const handle = () => {console.log(Math.random()); }; const throttleHandle = throttle(handle, 1000); throttleHandle(); throttleHandle();

精確的實現一個節流函數,無論是第一次之后還是最后一次(避免最后一次執行還會再等具體時間之后再執行)

// 精確的實現一個節流函數,無論是第一次之后還是最后一次(避免最后一次執行還會再等具體時間之后再執行) const throttle = (fn, delay) => {let timer = null;let startTime = Date.now();return function () {let curTime = null;let remainning = delay - (curTime - startTime);let context = this;let args = arguments;clearTimeout(timer);if (remainning <= 0) {fn.apply(context, args);startTime = Date.now();} else {timer = setTimeout(fn, remainning);}}; };

5. 你了解 Promise 嗎?平時用的多嗎?

5.1 Promise.all( ) 你知道有什么特性嗎?

解答Promise.all( ) 會接受一個 Promise 數組,數組里面可以是 Promise 也可以是一個常量或者其他;執行情況為:Promise 里面的所有 Promise 執行完成以后才會返回結果;

5.2如果其中一個 Promise 報錯了怎么辦?

解答:如果有一個報錯了,那么整個 Promise.all( ),就會返回一個 catch

5.3如果有一個 Promise 報錯了,那么其他的 Promise 還會執行嗎?

解答:會的,因為 Promise 是在創建之初(實例化) 的時候已經執行了

5.4 手寫一個Promise.all( )

面試官:“給你 三個 如下的 Promise ,調用你的Promise.all( )以后,看是否會在三秒以內返回對應的結果”

// 測試 const pro1 = new Promise((resolve, reject) => {setTimeout(() => {resolve("1");}, 1000); }); const pro2 = new Promise((resolve, reject) => {setTimeout(() => {resolve("3");}, 2000); }); const pro3 = new Promise((resolve, reject) => {setTimeout(() => {resolve("3");}, 3000); });// 測試題 const PromiseAll = (promiseArray) => {};

如何實現?

考點1:Promise.all( ) 里面的參數有可能不是一個 Promise,如何處理?

考點2:Promise.all( ) 返回值的順序,是你傳入的 Promise 順序,如何處理?

// 測試題 const PromiseAll = (promiseArray) => {return new Promise((resolve, reject) => {if (!Array.isArray(promiseArray)) {return reject(new Error("Type can only be array"));}const result = []; // promise 執行的結果集const promiseNums = promiseArray.length; // 當前循環次數let counter = 0; // 記錄當前 promise 執行順序,需要按照 傳入的 promise 順序返回for (let i = 0; i < promiseNums; i++) {Promise.resolve(promiseArray[i]).then((value) => {counter++;result.push(value);if (counter === promiseNums) {resolve(result);}}).catch((e) => reject(e));}}); };console.log(PromiseAll([pro1, pro2, pro3]).then((res) => {console.log(res);}).catch((e) => {console.log(e);}) );

5.5 Promise 在初始化的時候已經執行了,那么利用這個特性我們可以做點什么(擴展性問題)?

解答:可以利用 promise 的這個特性做緩存;

利用 裝飾器 + Map結構,實現一個 Promise 的緩存;

const cacheMap = new Map(); const enableCache = (target, name, descriptor) => {const val = descriptor.value;descriptor.value = async (...args) => {const cacheKey = name + JSON.stringify(args);if (!cacheMap.get(cacheKey)) {const cacheValue = Promise.resolve(val.apply(this, args)).catch((_) => {cacheMap.set(cacheKey, null);});cacheMap.set(cacheKey, cacheValue);}return cacheMap.get(cacheKey);};return descriptor; }; class PromiseClass {@enableCachestatic async getInfo() {} }PromiseClass.getInfo(); // 第一次發送請求 PromiseClass.getInfo(); // 第二次以后就是緩存 PromiseClass.getInfo(); PromiseClass.getInfo();

6. 字節經典算法題---- 接雨水

題干:

給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之后能接多少雨水。

示例1:

輸入 height = [0,1,0,2,1,0,1,3,2,1,2,1]

輸出:6

解釋:上面是由數組 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 單位的雨水(如上圖,藍色部分表示雨水)

示例2:

輸入 height = [4,2,0,3,2,5]

輸出:9

總結

以上是生活随笔為你收集整理的2022 前端一场面试及答案整理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。