天天看點

2021屆秋招騰訊前端一面面經

2021屆秋招騰訊前端一面面經

部門:qq音樂

方式:電話面試

javascript篇

自我介紹

學習前端多久

javascript常見的資料類型有哪些

<code>typeof null</code>傳回什麼

原始類型和對象類型有什麼差別

如何判斷是<code>object</code>還是<code>array</code>

有接觸過閉包嗎?閉包有哪些應用場景

js的垃圾回收機制

如何自己實作一個<code>new</code>

如何自己實作一個<code>instanceof</code>

原型鍊的最頂層是什麼(<code>null</code>)

原型鍊的繼承方式有哪些,舉例說明

原型鍊有沒有什麼缺點

子類<code>child</code>繼承了父類的<code>parent</code>之後,<code>oarent</code>有一個屬性name。這時<code>new</code>一個子類的執行個體<code>b</code>,如果修改了<code>b.name</code>是否會修改父類上的<code>name</code>屬性

http篇

如何用<code>ajax</code>原生實作一個<code>post</code>請求(xmlhttprequest)

其中有<code>readystate</code>,解釋一下它的每個值代表的含義

使用<code>ajax</code>如何解決跨域問題

使用<code>jsonp</code>時服務端傳回什麼樣的資料,如何處理(callback(json拼好))

dom篇

假設一個 <code>ul</code> 下有一萬個 <code>li</code>,<code>li</code> 的 <code>innerhtml</code> 是從 <code>0</code>到 <code>9999</code>,當點選某個 <code>li</code>時輸出該 <code>li</code> 代表的值,如何實作

<code>windowonload</code> 和 <code>domready</code> 哪個先觸發

浏覽器安全篇

講講 <code>csrf</code> 和 <code>xss</code> 攻擊的原理,和解決方式

假設有兩個 <code>tab</code>,一個是 <code>a.qq.com</code>,另一個是黑客的域名,你在黑客的域名下向 <code>a.qq.com</code> 發起了一個請求,請問是否會帶上 <code>a</code> 頁面的 <code>cookie</code>

算法篇

爬樓梯

答案:

共8種。包括7種基本資料類型:

表示空:<code>null</code>,<code>undefined</code>

三大件:<code>string</code>,<code>number</code>,<code>boolean</code>

兩個新類型:<code>bigint</code>,<code>symbol</code>

和<code>object</code>

解讀:

這裡是按照 mdn 的說法回答的。也可以回答為 7 種 基本 資料類型,和 引用 類型。引用類型包括:

普通對象 <code>object</code>

數組對象 <code>array</code>

正則對象 <code>regexp</code>

函數 <code>function</code>

這是目前最準确的方法,網上流傳了很多種判斷方法,這個是最核心的,答出這個就可以了。

除此之外,還有一種提問方式是 如何判斷是不是 array,這是偏向于考察 es6 新增的數組方法了,可以用<code>array.isarray()</code>和<code>instanceof</code>來回答。

2012 年以前,相對舊的浏覽器使用「引用-計數」算法(reference counting)進行垃圾回收,缺點是會由于循環應用導緻記憶體洩漏。現代浏覽器都使用「标記-清除」算法(mark and sweep),即從全局對象作為的根節點開始,向下查詢引用的對象,沒有查詢到的對象都将被回收。

相對舊的浏覽器如 ie6,ie7 是使用「引用-計數」法進行垃圾回收的。

先通過一個例子來了解 <code>new</code> 的作用吧:

代碼中我們建立了一個對象 <code>person</code>,它具有屬性 <code>name</code>,且在<code>person.prototype</code> 上定義了函數 <code>sayname</code>。

當我們通過 <code>new</code>建立一個新的執行個體 <code>p</code> 時,便同時具有了屬性 <code>p.name</code> 和 <code>p.sayname()</code>,關系如下圖:

2021屆秋招騰訊前端一面面經

知道了原理,就可以自己實作了。也就是說,自己寫一個函數 <code>funcnew()</code>,使得 <code>const p = new person('orange')</code> 和 <code>const p = funcnew('orange')</code> 得到的 <code>p</code> 完全相同,于是得到了答案中的代碼。

答案中最後一行代碼如何了解?

前面的例子我們隻考慮了 <code>person</code> 中沒有傳回值的情況,如有有傳回值,<code>new</code> 一個執行個體将會受到 <code>person</code> 中傳回值的影響。比如說:

上面的例子中,如果傳回了一個對象,我們需要傳回該對象;如果不是對象,則 <code>return</code> 沒用,正常處理。

這個問題既考察了 <code>instanceof</code> 的原理,又考察了原型鍊,還考察了代碼能力,是一個好問題。

在實作代碼中,我們判斷 <code>leftvalue</code> 是否為 <code>rightvalue</code> 的執行個體,思想是在 <code>leftvalue</code> 的原型鍊上,即 <code>leftvalue.__proto__</code> 上尋找是否存在 <code>rightvalue.prototype</code>。原理圖如下:

2021屆秋招騰訊前端一面面經

這需要我們熟練掌握原型鍊的相關知識。

2021屆秋招騰訊前端一面面經

假設一個 <code>ul</code> 下有一萬個 <code>li</code>,<code>li</code> 的 <code>innerhtml</code> 是從 <code>0</code> 到 <code>9999</code>,當點選某個 <code>li</code> 時輸出該 <code>li</code> 代表的值,如何實作

采用事件委托:

首先,我們當然不可能為每一個 <code>li</code> 标簽手動添加一個 <code>click</code> 事件(容易累死);其次,我們可能會想到使用 <code>for</code> 循環周遊每個元素,然後為其添加 <code>click</code> 事件,但這樣會頻繁操作 dom,降低性能,卡到爆炸。

而事件委托意義就在于此:減少 dom 操作,進而減少浏覽器的重繪與重排次數,提升性能。

事件委托的原理是,将 <code>li</code> 上監聽的 <code>click</code> 事件委托到 <code>ul</code>上。這裡運用到了 事件冒泡 的機制,即 <code>onclick</code> 事件以 <code>li -&gt; ul -&gt; body -&gt; html -&gt; document</code> 的冒泡順序逐漸傳遞。

是以,我們可以選擇在其中的 <code>ul</code> 上監聽 <code>click</code> 事件,進而實作事件委托。

如何建立 100000 個 <code>&lt;li&gt;</code> 呢?總不能複制粘貼 100000 次吧?

建立 100000個 <code>&lt;li&gt;</code> 标簽,思路是将 <code>0∼9999</code> 儲存在數組中,然後轉化為字元串 <code>"&lt;li&gt;0&lt;/li&gt;&lt;li&gt;1&lt;/li&gt;...&lt;li&gt;9999&lt;/li&gt;"</code>,最後将他們作為 <code>ul</code> 标簽的 <code>innerhtml</code> 即可。

2021屆秋招騰訊前端一面面經