1. 程式人生 > 其它 >JavaScript經典面試題的專業回答(一)

JavaScript經典面試題的專業回答(一)

面試官問:如何快速排查記憶體洩露?

相信我,面試的基調從一開始就定好了。面試官是往死裡問還是往平裡問,這都取決於看起來簡單卻需要猛料的回答。

1.地道解釋一下記憶體洩露

記憶體洩露的解釋:程式中己動態分配的堆記憶體由於某種原因未釋放或無法釋放。

面試官:那究竟是什麼原因導致沒有釋放呢?

  • 根據JS的垃圾回收機制,當記憶體中引用的次數為0的時候記憶體才會被回收
  • 全域性執行上下文中的物件被標記為不再使用才會被釋放

2.記憶體洩露的幾種場景

  • 全域性變數過多通常是變數未被定義或者胡亂引用了全域性變數
// main.js
// 場景1
function a(){
    b=10;
}
a();
b++;

// 場景2
setTimeout(()=>{
    console.log(b)
},1000) 
  • 閉包。 未手動解決必包遺留的記憶體引用。 定義了閉包就要消除閉包帶來的副作用。
 function closuer (){
    const b = 0;
    return (c)=> b + c
}

const render = closuer();

render();
render = null; // 手動設定為null,GC會自己去清除 
  • 事件監聽未被移除
 function addEvent (){
 const node =  document.getElementById('warp');
    node.addEventListener('touchmove',()=>{
        console.log('In Move');
    })
}

const onTouchEnd = (){
   const node =  document.getElementById('warp');
   node.
}

useEffect(()=>()=>{
     const node =  document.getElementById('warp');
     node.removeEventListener('touchmove');
}) // 類似react 生命週期函式: componentWillUnmount
render(<div id='warp' onTouchEnd={onTouchEnd}>
 // code...
</div>) 
  • 快取。 不管是啥快取,都需要設定好過期時間。

面試官: 那你能不能說說你是如何排查記憶體洩露的?

分析一波:到這,回答中規中矩。但面試官的問題真的就到這了嗎? 明顯不是。 面試官問你是如何排查問題,其實就是再問,你是如何定位到問題的。

也就是說,記憶體洩露會導致頁面卡頓,甚至是頁面崩潰。相信你在用APP得開發包或者開發包測試問題的時候,肯定遇到過整個APP閃退的事情,因為在真機器除錯的過程中難免會遇見記憶體不夠用的時候。

那麼,問題來了。 記憶體洩露會導致頁面卡頓或者崩潰,那頁面卡頓就是記憶體洩露導致的嗎? 所以面試官真正想問的是,你是如何發現某個頁面有可能發生了記憶體洩露,並且你是如何診斷該問題是記憶體洩漏引起的。

我在其它文章裡有提過,前端效能優化首先得確立一些效能指標,那記憶體洩漏不正式效能指標的一種嗎?那明確了指標不就是該去獲取相關資料,然後上報給效能平臺嗎?

3.記憶體洩漏相關效能指標的確立

  • window 物件上新增加的屬性數量
    • 在載入頁面之前Object.kyes(window)
    • 離開頁面(路由跳轉、頁面關閉、後臺APP關閉等)之前 Object.kyes(window)
  • 一些特殊函式,例如產生閉包的函式變數是否重新賦值為null. 也就是說你寫的閉包有被清理掉嗎?或者說,
 function closuer(){
    const a = 0;
    return (b)=> a + b
}
API.addClosuer(closuer);
const result = closuer();
API.addClosuer(result);
result = null;
closuer = null;

// 記錄頁面離開的時間,和被監聽的閉包函式有沒有被釋放。
const list = API.getClosuer(); // 被監聽的閉包函式集合,最好的結果就是 {closuer:null,result: null,...}
API.上報(API.getClosuer()); 

這樣,你的效能平臺上就能看見這一次上報的資料,頁面裡什麼時候產生了閉包,又是什麼時候閉包被清除了,也就一清二楚。

  • 事件觸發的次數以及事件處理的時間。

    • 如果js主執行緒堵塞了,那當下場景的事件觸發也就一定會延遲或者無限等待。 這裡用 performance.now
    • performance.now()方法返回當前網頁從performance.timing.navigationStart到當前時間之間的微秒數,其精度可達100萬分之一秒
    • performance.now() 近似等於 Date.now(),但前者返回的是毫秒,後者返回的是微秒,後者的精度比前者高1000倍。
  • 頁面DOM元素數量是否異常。

    • 深度優先遍歷,獲取DOM樹的深度。這裡可以根據不同場景不同頁面來設定DOM樹深度的最大閥值。超過最大閥值則平臺進行預警。 因為這意味著頁面有動態新增DOM的事情發生。

    • FPS,有明顯長波段的不平穩。

    • 重繪的次數。

最後

為了讓大家快速精通JavaScript,在這裡免費分享給大家一份Javascript學習指南。

Javascript學習指南文件涵蓋了javascript 語言核心、詞法結構 、型別、值和變數 、表示式和運算子 、語句、物件 、陣列 、函式 、類和模組 、 正則表示式的模式匹配、 javascript的子集和擴充套件 、伺服器端javascript /客戶端javascript 、web瀏覽器中的javascript 、window物件 、指令碼化文件、指令碼化css 、事件處理等22章知識點。內容豐富又詳細,拿下網際網路一線公司offfer的小夥伴都在看。

每個知識點都有左側導航書籤頁,看的時候十分方便,由於內容較多,下面列舉的部分內容和圖片。

物件

  • 建立物件
  • 屬性的查詢和設定
  • 刪除屬性
  • 檢測屬性
  • 列舉屬性
  • 屬性getter和setter
  • 屬性的特性

陣列

  • 建立陣列
  • 陣列元素的讀和寫
  • 稀疏陣列
  • 陣列長度
  • 陣列元素的新增和刪除
  • 陣列遍歷
  • 多維陣列

函式

  • 函式定義
  • 函式呼叫
  • 函式的實參和形參
  • 作為值的函式
  • 作為名稱空間的函式
  • 閉包
  • 函式屬性、方法和建構函式

類和模組

  • 類和原型
  • 類和建構函式
  • javascript中java式的類繼承
  • 類的擴充
  • 類和型別
  • javascript中的面向物件技術
  • 子類

正則表示式的模式匹配

  • 正則表示式的定義
  • 用於模式匹配的string方法
  • regexp物件

javascript的子集和擴充套件

  • javascript的子集
  • 常量和區域性變數
  • 解構賦值
  • 迭代
  • 函式簡寫
  • 多catch 從句
  • e4x: ecmascript for xml


web瀏覽器中的javascript

  • 客戶端javascript
  • 在html裡嵌入javascript
  • javascript程式的執行
  • 相容性和互用性
  • 可訪問性
  • 安全性
  • 客戶端框架


window物件

  • 計時器
  • 瀏覽器定位和導航
  • 瀏覽歷史
  • 瀏覽器和螢幕資訊
  • 對話方塊
  • 錯誤處理
  • 作為window物件屬性的文件元素

如果你有其他語言的程式設計經歷,這份文件會有助你瞭解JavaScript是一門高階的、動態的、弱型別的程式語言,非常適合面向物件和函式式的程式設計風格。

我在這裡將這份完整版的JS學習指南電子版文件提供出來,感興趣的朋友都可以找我拿一份學習!(純免費的一個分享,希望能給大家帶來實質性的幫助)

快速入手通道:【點選這領取Javascript學習指南電子版】

你的支援,我的動力;祝各位前程似錦,offer不斷!!!