八月面试题(2) 2018-9-6
1、 什么是重繪(Repaint)和回流(Reflow)?
哪些動作可能會導(dǎo)致重繪(Repaint)和回流(Reflow)的發(fā)生?
重繪(Repaint)和回流(Reflow)和Event loop的關(guān)系?
如何減少重繪(Repaint)和回流(Reflow)?
答: 重繪和回流是渲染步驟中的一小節(jié),但是這兩個(gè)步驟對于性能影響很大。 1. 重繪是當(dāng)節(jié)點(diǎn)需要更改外觀而不會影響布局的,比如改變?color?就叫稱為重繪 2. 回流是布局或者幾何屬性需要改變就稱為回流。
回流必定會發(fā)生重繪,重繪不一定會引發(fā)回流。回流所需的成本比重繪高的多,改變深層次的節(jié)點(diǎn)很可能導(dǎo)致父節(jié)點(diǎn)的一系列回流。 所以以下幾個(gè)動作可能會導(dǎo)致性能問題:
- 改變 window 大小
- 改變字體
- 添加或刪除樣式
- 文字改變
- 定位或者浮動
- 盒模型
很多人不知道的是,重繪和回流其實(shí)和 Event loop 有關(guān)。
- 當(dāng) Event loop 執(zhí)行完 Microtasks 后,會判斷 document 是否需要更新。因?yàn)闉g覽器是 60Hz 的刷新率,每 16ms 才會更新一次。
- 然后判斷是否有?resize?或者?scroll?,有的話會去觸發(fā)事件,所以?resize?和?scroll?事件也是至少 16ms 才會觸發(fā)一次,并且自帶節(jié)流功能。
- 判斷是否觸發(fā)了 media query
- 更新動畫并且發(fā)送事件
- 判斷是否有全屏操作事件
- 執(zhí)行?requestAnimationFrame?回調(diào)
- 執(zhí)行?IntersectionObserver?回調(diào),該方法用于判斷元素是否可見,可以用于懶加載上,但是兼容性不好
- 更新界面
- 以上就是一幀中可能會做的事情。如果在一幀中有空閑時(shí)間,就會去執(zhí)行?requestIdleCallback?回調(diào)。
少重繪和回流 使用?translate?替代?top
- 使用?visibility?替換?display: none?,因?yàn)榍罢咧粫鹬乩L,后者會引發(fā)回流(改變了布局)
- 把 DOM 離線后修改,比如:先把 DOM 給?display:none?(有一次 Reflow),然后你修改100次,然后再把它顯示出來
- 不要把 DOM 結(jié)點(diǎn)的屬性值放在一個(gè)循環(huán)里當(dāng)成循環(huán)里的變量
for(let i = 0; i < 1000; i++) { // 獲取 offsetTop 會導(dǎo)致回流,因?yàn)樾枰カ@取正確的值 console.log(document.querySelector('.test').style.offsetTop) }
不要使用 table 布局,可能很小的一個(gè)小改動會造成整個(gè) table 的重新布局
- 動畫實(shí)現(xiàn)的速度的選擇,動畫速度越快,回流次數(shù)越多,也可以選擇使用?requestAnimationFrame
- CSS 選擇符從右往左匹配查找,避免 DOM 深度過深
- 將頻繁運(yùn)行的動畫變?yōu)閳D層,圖層能夠阻止該節(jié)點(diǎn)回流影響別的元素。比如對于?video?標(biāo)簽,瀏覽器會自動將該節(jié)點(diǎn)變?yōu)閳D層。
2、 https抓包的原理是什么?平時(shí)你用什么工具?如何抓包?
3、什么是無頭瀏覽器?它的作用是什么?
4、請說一下V8下的垃圾回收機(jī)制
答:V8 實(shí)現(xiàn)了準(zhǔn)確式 GC,GC 算法采用了分代式垃圾回收機(jī)制。因此,V8 將內(nèi)存(堆)分為新生代和老生代兩部分。 新生代算法 新生代中的對象一般存活時(shí)間較短,使用 Scavenge GC 算法。 在新生代空間中,內(nèi)存空間分為兩部分,分別為 From 空間和 To 空間。在這兩個(gè)空間中,必定有一個(gè)空間是使用的,另一個(gè)空間是空閑的。新分配的對象會被放入 From 空間中,當(dāng) From 空間被占滿時(shí),新生代 GC 就會啟動了。算法會檢查 From 空間中存活的對象并復(fù)制到 To 空間中,如果有失活的對象就會銷毀。當(dāng)復(fù)制完成后將 From 空間和 To 空間互換,這樣 GC 就結(jié)束了。 #老生代算法
老生代算法 老生代中的對象一般存活時(shí)間較長且數(shù)量也多,使用了兩個(gè)算法,分別是標(biāo)記清除算法和標(biāo)記壓縮算法。 在講算法前,先來說下什么情況下對象會出現(xiàn)在老生代空間中: 新生代中的對象是否已經(jīng)經(jīng)歷過一次 Scavenge 算法,如果經(jīng)歷過的話,會將對象從新生代空間移到老生代空間中。 To 空間的對象占比大小超過 25 %。在這種情況下,為了不影響到內(nèi)存分配,會將對象從新生代空間移到老生代空間中。 老生代中的空間很復(fù)雜,有如下幾個(gè)空間
enum AllocationSpace { 復(fù)制代碼// TODO(v8:7464): Actually map this space's memory as read-only. RO_SPACE, // 不變的對象空間 NEW_SPACE, // 新生代用于 GC 復(fù)制算法的空間 OLD_SPACE, // 老生代常駐對象空間 CODE_SPACE, // 老生代代碼對象空間 MAP_SPACE, // 老生代 map 對象 LO_SPACE, // 老生代大空間對象 NEW_LO_SPACE, // 新生代大空間對象
FIRST_SPACE = RO_SPACE, LAST_SPACE = NEW_LO_SPACE, FIRST_GROWABLE_PAGED_SPACE = OLD_SPACE, LAST_GROWABLE_PAGED_SPACE = MAP_SPACE }; 在老生代中,以下情況會先啟動標(biāo)記清除算法:
- 某一個(gè)空間沒有分塊的時(shí)候
- 空間中被對象超過一定限制
- 空間不能保證新生代中的對象移動到老生代中
在這個(gè)階段中,會遍歷堆中所有的對象,然后標(biāo)記活的對象,在標(biāo)記完成后,銷毀所有沒有被標(biāo)記的對象。在標(biāo)記大型對內(nèi)存時(shí),可能需要幾百毫秒才能完成一次標(biāo)記。這就會導(dǎo)致一些性能上的問題。為了解決這個(gè)問題,2011 年,V8 從 stop-the-world 標(biāo)記切換到增量標(biāo)志。在增量標(biāo)記期間,GC 將標(biāo)記工作分解為更小的模塊,可以讓 JS 應(yīng)用邏輯在模塊間隙執(zhí)行一會,從而不至于讓應(yīng)用出現(xiàn)停頓情況。但在 2018 年,GC 技術(shù)又有了一個(gè)重大突破,這項(xiàng)技術(shù)名為并發(fā)標(biāo)記。該技術(shù)可以讓 GC 掃描和標(biāo)記對象時(shí),同時(shí)允許 JS 運(yùn)行,你可以點(diǎn)擊?該博客?詳細(xì)閱讀。
清除對象后會造成堆內(nèi)存出現(xiàn)碎片的情況,當(dāng)碎片超過一定限制后會啟動壓縮算法。在壓縮過程中,將活的對象像一端移動,直到所有對象都移動完成然后清理掉不需要的內(nèi)存。
5、線性順序存儲結(jié)構(gòu)和鏈?zhǔn)酱鎯Y(jié)構(gòu)有什么區(qū)別?以及優(yōu)缺點(diǎn)。
答: 順序存儲結(jié)構(gòu)和鏈?zhǔn)酱鎯Y(jié)構(gòu)的區(qū)別 鏈表存儲結(jié)構(gòu)的內(nèi)存地址不一定是連續(xù)的,但順序存儲結(jié)構(gòu)的內(nèi)存地址一定是連續(xù)的; 鏈?zhǔn)酱鎯m用于在較頻繁地插入、刪除、更新元素時(shí),而順序存儲結(jié)構(gòu)適用于頻繁查詢時(shí)使用。
順序存儲結(jié)構(gòu)和鏈?zhǔn)酱鎯Y(jié)構(gòu)的優(yōu)缺點(diǎn): 空間上 順序比鏈?zhǔn)焦?jié)約空間。是因?yàn)殒準(zhǔn)浇Y(jié)構(gòu)每一個(gè)節(jié)點(diǎn)都有一個(gè)指針存儲域。 存儲操作上: 順序支持隨機(jī)存取,方便操作 插入和刪除上: 鏈?zhǔn)降囊软樞虻姆奖?#xff08;因?yàn)椴迦氲脑掜樞虮硪埠芊奖?#xff0c;問題是順序表的插入要執(zhí)行更大的空間復(fù)雜度,包括一個(gè)從表頭索引以及索引后的元素后移,而鏈表是索引后,插入就完成了) 例如:當(dāng)你在字典中查詢一個(gè)字母j的時(shí)候,你可以選擇兩種方式,第一,順序查詢,從第一頁依次查找直到查詢到j(luò)。第二,索引查詢,從字典的索引中,直接查出j的頁數(shù),直接找頁數(shù),或許是比順序查詢最快的。
轉(zhuǎn)載于:https://juejin.im/post/5b911a635188255c652d1c3b
總結(jié)
以上是生活随笔為你收集整理的八月面试题(2) 2018-9-6的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端要凉?微软开源Sketch2Code
- 下一篇: Java GUI:将JPanel添加进J