目錄
面試官:什么是防抖和節(jié)流,他們的應(yīng)用場景有哪些?
面試官:js中什么是可選操作符,如何訪問數(shù)組?
面試官:請簡述一下 event loop
面試官:請簡述 node/v8 中的垃圾回收機制
面試官:如何刪除項目中沒有使用到的 package?
面試官:請你談?wù)?js 中在 new 的時候發(fā)生了什么?
面試官:瀏覽器的剪切板中如何監(jiān)聽復(fù)制事件?
面試官:如何實現(xiàn)頁面文本不可復(fù)制?
面試官:異步加載 JS 腳本時,async 與 defer 有何區(qū)別?
面試官:前端如何實現(xiàn)文件上傳功能?
????????每天10道題,100天后,搞定所有前端面試的高頻知識點,加油!??!,在看文章的同時,希望不要直接看答案,先思考一下自己會不會,如果會,自己的答案是什么?想過之后再與答案比對,是不是會更好一點,當(dāng)然如果你有比我更好的答案,歡迎評論區(qū)留言,一起探討技術(shù) 之美。
面試官:什么是防抖和節(jié)流,他們的應(yīng)用場景有哪些?
我:呃~,防抖和節(jié)流以及他們的應(yīng)用場景總結(jié)如下:
防抖:顧名思義就是防止抖動,以免把一次事件誤認(rèn)為是多次,敲鍵盤就是一個每天都會接觸到的防抖操作,在JS中有好多防抖的場景,例如:登錄、發(fā)短信等按鈕避免用戶點擊太快,以致于發(fā)送了多次請求,需要防抖;調(diào)整瀏覽器窗口大小時,resize 次數(shù)過于頻繁,造成計算過多,此時需要一次到位,就用到了防抖;代碼如下,可以看出來防抖重在清零:
function debounce(f, wait) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { f(...args); }, wait); }; }
節(jié)流:節(jié)流,顧名思義,控制水的流量??刂剖录l(fā)生的頻率,如控制為 1s 發(fā)生一次,甚至 1 分鐘發(fā)生一次。與服務(wù)端(server)及網(wǎng)關(guān)(gateway)控制的限流 (Rate Limit) 類似,在JS中有好多節(jié)流的場景,例如:scroll事件,每隔一秒計算一次位置信息等;瀏覽器播放事件,每個一秒計算一次進(jìn)度信息等;input 框?qū)崟r搜索并發(fā)送請求展示下拉列表,每隔一秒發(fā)送一次請求 (也可做防抖);代碼如下,可以看出來節(jié)流重在加鎖:
function throttle(f, wait) { let timer; return (...args) => { if (timer) { return; } timer = setTimeout(() => { f(...args); timer = null; }, wait); }; }
總結(jié):
防抖:防止抖動,單位時間內(nèi)事件觸發(fā)會被重置,避免事件被誤傷觸發(fā)多次。代碼實現(xiàn)重在清零 clearTimeout。防抖可以比作等電梯,只要有一個人進(jìn)來,就需要再等一會兒。業(yè)務(wù)場景有避免登錄按鈕多次點擊的重復(fù)提交。
節(jié)流:控制流量,單位時間內(nèi)事件只能觸發(fā)一次,與服務(wù)器端的限流 (Rate Limit) 類似。代碼實現(xiàn)重在開鎖關(guān)鎖 timer=timeout; timer=null。節(jié)流可以比作過紅綠燈,每等一個紅燈時間就可以過一批。
面試官:js中什么是可選操作符,如何訪問數(shù)組?
我:呃~,?. 操作符,可以嵌套獲取對象的屬性值。通過獲取對象屬性獲得的值可能是 undefined 或 null 時,可選鏈操作符提供了一種方法來簡化被連接對象的值訪問。具體使用方式如下:
const o = {};
// 添加可選鏈之前
o && o.a && o.a.b && o.a.b.c && o.a.b.c.d;
// 添加可選鏈之后
o?.a?.b?.c?.d;
const obj = { a: [1, 2], b() {} };
// 訪問數(shù)組
obj?.a?.[0];
//使用方法
obj?.b?.();
面試官:請簡述一下 event loop
我:呃~,因為 JS 是單線程的,單線程就意味著,所有任務(wù)需要排隊,前一個任務(wù)結(jié)束,才會執(zhí)行后一個任務(wù)。為了解決排除等待問題,JS 的任務(wù)分為同步任務(wù)(synchronous)和異步任務(wù)(asynchronous)。 所有同步任務(wù)都在主線程上執(zhí)行,形成一個 Stack)。異步任務(wù)(如果是 WebAPI 則會進(jìn)入 WebAPI,例如 ajax setTimeout)不進(jìn)入主線程,而是進(jìn)入另一 Callback Queue。同步任務(wù)順序執(zhí)行,只有執(zhí)行棧中的同步任務(wù)執(zhí)行完了,系統(tǒng)才會讀取任務(wù)隊列中可以執(zhí)行的異步任務(wù),才會把此異步任務(wù)從事件隊列中放入執(zhí)行棧中執(zhí)行,如此循環(huán),直至所有任務(wù)執(zhí)行完畢。這就是 EventLoop。代碼如下:
setTimeout(() => console.log(0));
new Promise((resolve) => {
console.log(1);
resolve(2);
console.log(3);
}).then((o) => console.log(o));
new Promise((resolve) => {
console.log(4);
resolve(5);
})
.then((o) => console.log(o))
.then(() => console.log(6));
輸出內(nèi)容如下:
面試官:請簡述 node/v8 中的垃圾回收機制
我:呃~,v8 中的垃圾回收機制分為如下三種:
Scavenge:工作在新生代,把 from space 中的存活對象移至 to space
Mark-Sweep:標(biāo)記清除。新生代的某些對象由于過度活躍會被移至老生代,此時對老生代中活對象進(jìn)行標(biāo)記,并清理死對象
Mark-Compac:標(biāo)記整理。
當(dāng)一個函數(shù)執(zhí)行結(jié)束之后,JavaScript 引擎會通過向下移動 ESP 來銷毀該函數(shù)保存在棧中的執(zhí)行上下文。 要回收堆中的垃圾數(shù)據(jù),就需要用到 JavaScript 中的垃圾回收器了。 代際假說(The Generational Hypothesis),是垃圾回收領(lǐng)域中一個重要的術(shù)語,后續(xù)垃圾回收的策略都是建立在該假說的基礎(chǔ)之上的,所以很是重要。 代際假說有以下兩個特點:
1)大部分對象在內(nèi)存中存在的時間很短,簡單來說,就是很多對象一經(jīng)分配內(nèi)存,很快就變得不可訪問;
2)是不死的對象,會活得更久。 在 V8 中會把堆分為新生代和老生代兩個區(qū)域,新生代中存放的是生存時間短的對象,老生代中存放的生存時間久的對象。 ● 副垃圾回收器,主要負(fù)責(zé)新生代的垃圾回收。 ● 主垃圾回收器,主要負(fù)責(zé)老生代的垃圾回收。
?使用增量標(biāo)記算法,可以把一個完整的垃圾回收任務(wù)拆分為很多小的任務(wù),這些小的任務(wù)執(zhí)行時間比較短,可以穿插在其他的 JavaScript 任務(wù)中間執(zhí)行,增強用戶體驗。
面試官:如何刪除項目中沒有使用到的 package?
我:呃~,可以采用 depcheck 來完成這件事,代碼如下:
npm install depcheck -g
面試官:請你談?wù)?js 中在 new 的時候發(fā)生了什么?
我:呃~,在js中進(jìn)行new的時候,發(fā)生了下面的四步:
1)創(chuàng)建了一個新對象
2)鏈接到原型
3)綁定這個指向
4)返回這個對象
function _new() {
let obj = {};
let Con = [].shift.call(arguments);
obj.__proto__ = Con.prototype;
let result = Con.apply(obj, arguments);
return typeof obj === "object" ? obj : {};
}
面試官:瀏覽器的剪切板中如何監(jiān)聽復(fù)制事件?
我:呃~,可以采用原生js發(fā)方式進(jìn)行監(jiān)聽,如下:
// 在 HTML 元素上
<input oncopy="cb" />
// 在 JS 中獲取具體元素
document.querySelector("p").oncopy = cb;
document.oncopy = cb;
// 或
document.querySelector("p").addEventListener("copy", cb);
document.addEventListener("copy", cb);
面試官:如何實現(xiàn)頁面文本不可復(fù)制?
我:呃~,有CSS和JS兩種方法,以下任選其一或結(jié)合使用即可。
使用CSS如下:
user-select: none;
使用JS如下,監(jiān)聽 selectstart 事件,禁止選中,當(dāng)用戶選中一片區(qū)域時,將觸發(fā) selectstart 事件,Selection API 將會選中一片區(qū)域。禁止選中區(qū)域即可實現(xiàn)頁面文本不可復(fù)制:
document.body.onselectstart = (e) => { e.preventDefault(); }; document.body.oncopy = (e) => { e.preventDefault(); };
面試官:異步加載 JS 腳本時,async 與 defer 有何區(qū)別?
我:呃~,在正常情況下,即 <script> 沒有任何額外屬性標(biāo)記的情況下,有幾點共識JS 的腳本分為加載、解析、執(zhí)行幾個步驟,簡單對應(yīng)到圖中就是 fetch (加載) 和 execution (解析并執(zhí)行)JS 的腳本加載(fetch)且執(zhí)行(execution)會阻塞 DOM 的渲染,因此 JS 一般放到最后頭
而 defer 與 async 的區(qū)別如下:
相同點:異步加載 (fetch)
不同點:
async 加載(fetch)完成后立即執(zhí)行 (execution),因此可能會阻塞 DOM 解析;
defer 加載(fetch)完成后延遲到 DOM 解析完成后才會執(zhí)行(execution)**,但會在事件 DomContentLoaded 之前文章來源:http://www.zghlxwxcb.cn/news/detail-404245.html
面試官:前端如何實現(xiàn)文件上傳功能?
我:呃~,將 input 的類型設(shè)置為 file,再加一個按鈕就行,如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-404245.html
<input type="file" ref="referenceUpload" @change="onUpload"></input> <button type="primary" style="margin: 0px 0px 0px -83px;">上傳文件</button>
到了這里,關(guān)于【手撕面試題】JavaScript(高頻知識點三)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!