面試必備良藥之前端Q本周N題匯總
- 2019 年 12 月 21 日
- 筆記
背景
最近起了一個新項目,叫每周N題,N<=5。前端面試題雖然五花八門,但是我們也確實可以從中學到知識。所以我覺得應該有個地方收錄一下,每周做幾題,既可以考驗自己知識的廣度又可以挖掘深度,挺好的。
github地址:https://github.com/LuckyWinty/fe-weekly-questions,點擊即可到達題庫哦~
參與步驟:
- 打開地址,點 star
- watch 項目,及時收到題目的更新及答案消息
- 有自己會的題目 ,點comment,留下答案,大家交流學習
本周題目匯總
1. 如何判斷左右小括號是否全部匹配。如 ( ( ))()((((()))))
思路:利用棧,先進後出的特性
參考答案(答案不嚴謹,請到GitHub參考):
const judgeBracketsMatch = (s)=> { const result = []; for(let i = 0;i < s.length;i++){ if(s[i] === '('){ result.push(s[i]) } if(s[i] === ')'){ result.pop() } } if(result.length){ return false }else{ return true } }
2. 下面代碼中的 a 在什麼情況下會打印1?
var a = ?if(a == 1 && a == 2 && a == 3){console.log(1)}
思路:重寫 valueOf 方法 參考答案:
var a = { value: 0, valueOf(){ return ++this.value }} if (a == 1 && a == 2 && a == 3) { console.log(1);}
3. 如何理解迴流和重繪
迴流:
當我們對 DOM 的修改引發了 DOM 幾何尺寸的變化(比如修改元素的寬、高或隱藏元素等)時,瀏覽器需要重新計算元素的幾何屬性(其他元素的幾何屬性和位置也會因此受到影響),然後再將計算的結果繪製出來。這個過程就是迴流(也叫重排)。
重繪:
當我們對 DOM 的修改導致了樣式的變化、卻並未影響其幾何屬性(比如修改了顏色或背景色)時,瀏覽器不需重新計算元素的幾何屬性、直接為該元素繪製新的樣式(跳過了上圖所示的迴流環節)。這個過程叫做重繪。由此我們可以看出,重繪不一定導致迴流,迴流一定會導致重繪。
常見的會導致迴流的元素:
- 常見的幾何屬性有 width、height、padding、margin、left、top、border 等等。
- 最容易被忽略的操作:獲取一些需要通過即時計算得到的屬性,當你要用到像這樣的屬性:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight 時,瀏覽器為了獲取這些值,也會進行迴流。
- 當我們調用了 getComputedStyle 方法,或者 IE 里的 currentStyle 時,也會觸發迴流。原理是一樣的,都為求一個「即時性」和「準確性」。
避免方式:
- 避免逐條改變樣式,使用類名去合併樣式
- 將 DOM 「離線」,使用DocumentFragment
- 提升為合成層,如使用
will-change
#divId { will-change: transform;}
優點
- 合成層的位圖,會交由 GPU 合成,比 CPU 處理要快
- 當需要 repaint 時,只需要 repaint 本身,不會影響到其他的層
- 對於 transform 和 opacity 效果,不會觸發 layout 和 paint
注意:
部分瀏覽器緩存了一個 flush 隊列,把我們觸發的迴流與重繪任務都塞進去,待到隊列里的任務多起來、或者達到了一定的時間間隔,或者「不得已」的時候,再將這些任務一口氣出隊。但是當我們訪問一些即使屬性時,瀏覽器會為了獲得此時此刻的、最準確的屬性值,而提前將 flush 隊列的任務出隊。
4. UDP和TCP有什麼區別?
- TCP協議在傳送數據段的時候要給段標號;UDP協議不
- TCP協議可靠;UDP協議不可靠
- TCP協議是面向連接;UDP協議採用無連接
- TCP協議負載較高,採用虛電路;UDP採用無連接
- TCP協議的發送方要確認接收方是否收到數據段(3次握手協議)
- TCP協議採用窗口技術和流控制
特性 |
TCP |
UDP |
---|---|---|
是否連接 |
面向連接 |
面向非連接 |
傳輸可靠性 |
可靠 |
不可靠 |
應用場合 |
傳輸大量數據 |
傳輸少量數據 |
速度 |
慢 |
快 |
5. 實現一個LazyMan,可以按照以下方式調用
實現一個LazyMan,可以按照以下方式調用:LazyMan('Hank')輸出:Hi! This is Hank!LazyMan('Hank').sleep(10).eat('dinner')輸出Hi! This is Hank!//等待10秒..Wake up after 10Eat dinner~LazyMan('Hank').sleep(10).eat('dinner').eat('supper')輸出Hi This is Hank!Eat dinner~Eat supper~LazyMan('Hank').sleepFirst(5).eat('supper')輸出//等待5秒Wake up after 5Hi This is Hank!Eat supper~以此類推。
思路:參考Generator實現,可以控制執行和停止 參考答案:
function LazyMan(name) { if(!(this instanceof LazyMan)){ return new LazyMan(name) } const cb = (next)=>{ console.log(`Hi This is ${name}!`) next() } this.cbs = [cb]; setTimeout(()=>{ this.next() },0)}LazyMan.prototype.eat = function (food){ const cb = (next)=>{ console.log(`Eat ${food}~`) next() } this.cbs.push(cb); return this}LazyMan.prototype.sleepFirst = function (time){ const cb = (next)=>{ setTimeout(()=>{ next() },time*1000) } this.cbs.unshift(cb); return this}LazyMan.prototype.sleep = function(time){ const cb = (next)=>{ setTimeout(()=>{ next() },time*1000) } this.cbs.push(cb); return this}LazyMan.prototype.next = function(){ if(this.cbs.length <= 0)return const first = this.cbs.shift() first(this.next.bind(this))}
小結
本周題目,還是比較考驗深度的,建議大家都動手做一下。更多題目查看這裡:
github地址:https://github.com/LuckyWinty/fe-weekly-questions,點擊即可到達題庫哦~