1. 程式人生 > >騰訊2018春招實習生和秋招面試問題

騰訊2018春招實習生和秋招面試問題

2018.04.18

首先,我先說說整個過程吧。(如果對過程不感興趣的話可以直接拉到下面的面試題)

筆試(我覺得考的稀爛,以為沒有面試機會的)結束後大概一週,下來了面試通知,下午三點半。

我從我們大學提前一個半小時從實驗室出發的,到目的地的時候差不多2:50分了,三點的時候我找到了會議中心一樓,然後進去看到大廳兩旁都有工作人員在長桌面前坐著,一部分是答疑指引方向,一部分負責簽到啥的等等,我去到簽到的地方問工作人員,那個男士貌似有點不耐煩的跟我說掃碼簽到就好了。我覺得奇怪,人長的挺帥的,但是服務態度怎麼這麼差呢?但是我掃碼之後我還是道了聲謝謝,最起碼的禮儀還是要得,然後又繼續問他,然後該怎麼辦,他說進去會議廳找個位置等著就好了,微信公眾號會提示你面試的具體廳號和桌號。

然後,我就走進了會議廳,尼瑪!嚇屎勞資了!我特麼還以為進錯地方了!只見我擡頭看到了好幾把多的人,幾乎坐滿了整個廳的2/3了!關鍵是那個廳很大!能坐估計四百人!我在想一個實習生面試怎麼搞的像人才市場一樣啊?後來還是想想,人家是頂級網際網路公司,只有這個規模才能配得上吧。

隨後,等了不到十分鐘,就輪到我了...懷著忐忑的心情去到了我所在的面試官位置。

好,開始正題。

面試官:你是xx(姓名)對吧?

我:是的,是的,前輩您好。

面試官:好,先做個自我介紹吧?(第一個問題)

我:(...由於緊張,頭腦開始空白,不知道自我介紹從哪說起,隨後覺得這樣不行,就深吸了一口氣說道)您好,我是吧啦吧啦......我平常的時間除了科研論文之外,剩餘的時間基本上都用來學習前端了(騙子!才沒有呢!其實我前兩天準備的自我介紹中準備還說我偶爾運動放鬆一下,但是到現場之後由於緊張忘記了!)。我學習前端總共有這麼幾種方式(我之前準備的有七種):

第一種,看書。看過的書有《js高階程式設計第三版》、《web效能指南》等;

第二種:看技術部落格。常去的有csdn、部落格園等;

第三種:做筆試題和麵試題。因為每當自己遇到不懂的或者不會做的,就會去谷歌搜尋;

第四種:自己寫部落格總結。寫部落格有助於我對前端知識體系的理解,記錄自己的成長;

第五種:通過實習學習。在實習中,通過實踐可以更加深入的理解理論,而不是停留在表面。

漏掉的兩種:

1)和同學們(都搞前端)交流。因為通過這種分享與討論的方式可以更加鞏固知識和加深對知識的理解;

2)通過線上資源。網上有很多的前端網路資源,比如像慕課網、極客學院、騰訊課堂等,上面的資源都比較優質。

面試官(看了看我的簡歷):那你說說你做專案的時候都用了哪些基礎知識?(第二個問題)

我:(...我勒個去!這個問題尼瑪把我問懵了...我該怎麼回答?好像沒用到啥基礎知識啊...我支支吾吾了十幾秒,實在擠不出啥話可以回答的,那時我就想,我得引導面試官才行,就說)用到的有面向物件設計、繼承啥的。(我擦!這尼瑪叫回答?而且專案中根本沒用到好不好?慚愧啊!)

面試官:那好,你說說繼承吧?(第三個問題)

我:繼承的方式有六種(js高階程式設計裡講的),有原型鏈、組合繼承、寄生式繼承、繼承組合式繼承。(漏掉了兩種,1)借用建構函式;2)原型式繼承)程式設計師最常用的是組合式繼承。

面試官:那你寫一個繼承吧。(第四個問題)

我(只能憑藉看書的記憶寫下程式碼):程式碼如下

function Person(){
    this.name = 'Charles',
    this.age = 24,
    this.sayName = function(){
        console.log(this.name);
    }
}
Person.prototype.sayHello = function(){
    console.log('hello');
}
var Person1 = new Person;
Person1.name = 'Tom';
Person1.sayName();//Tom
console.log(Person1.age);//24
Person1.sayHello();//hello

我原本是打算這樣寫的,也知道這個原理。但是很遺憾,由於緊張,把Person1.sayName()的值給寫成Charles了,擦。真的是在面試中不能緊張啊!只有冷靜才能幫你清醒思路。(PS:這是原型鏈繼承,跟我說的組合繼承關係並不大,大寫的尷尬...)要想把相關知識都複習一遍,可以參考連結:點選開啟連結

面試官(看了一眼就放在一邊了....):跟我說一說閉包吧。(第五個問題)

我:閉包的概念是能有權訪問其他函式內的變數的函式。(我看了面試官一眼,從他的表情上來看這個答案並不合他的意)由於閉包可以稱作是函式內的函式,由於js在執行閉包外的函式時,閉包會快取外部函式的作用域,所以在執行完外部函式之後,外部函式內的變數並不會立刻銷燬,故閉包才可以訪問到外部函式內的變數。

面試官:你的意思是內部函式能訪問到外部函式內的變數,那外部函式是不能訪問內部函式的變數的是嗎?

我:是的。

面試官:那有沒有一種方法或者是方式可以實現外部函式能訪問到內部函式內的變數呢?(第六個問題)

我(我擦,完了,這個問題我不會怎麼辦?):讓我好好想一想,您可以借我一張紙嗎?(馬德,現在的我真的好想打屎我自己,裝什麼逼啊,還特麼要張紙!不會就是不會)在紙上描繪了半天后,回答:不知道....

面試官:那我們跳過這個問題吧。

我:那您能不能告訴我可以實現的一個方法呢?

面試官:可以在裡面建立一個匿名函式,在匿名函式裡面返回需要的變數。

我:噢~~~(裝作懂了的樣子)

面試官:現在有一個實時更新的資料,要把這個資料展示在頁面,你怎麼實現?(第七個問題)

我:可以使用setInterval方法,每隔一段時間就更新一次資料。但是我覺得setInterval這個方法不太好,比較耗效能,不可取。我再想想看有沒有其他的方法可以實現。

面試官:嗯,你說的setInterval方法的確可以實現,也確實存在著你說的缺點。

我(支支吾吾了半天):可以通過for迴圈遍歷的形式嗎?

面試官:你說的遍歷好像也只能遍歷當時某一刻的資料,並不是實時更新的資料

我(考慮到請求最好只有一次,於是聯想到了陣列):那可不可以像彈幕那樣,每出來一個新的資料就把原先第一個資料給刪除掉,螢幕上顯示的彈幕總個數是固定的,遵循先進先出的原則。

面試官:你這個想法只是對資料的處理,我的問題是怎麼顯示實時更新的資料

我(窩草,居然帶不偏):這個我暫時想不出什麼辦法了。

面試官:那你得下去自己好好了解下了,跳過這個問題吧。使用者從地址輸入欄輸入網址回車到頁面展示的這個過程都發生了什麼?(第八個問題)

我(我勒個去!我之前在別人的部落格上看到了這個題目的解答過程,但是今天特麼的忘記了!悔死了!):我嘗試著說下我自己的理解。首先是用將網址輸入後,然後回車,瀏覽器把要傳送的資料和頭部發送給伺服器...然後...想不出來了。

面試官(皺了皺眉,表示不滿意):既然這樣的話,那我們跳過吧。

我:我之前有在部落格上看到過,可能當時有些過程不太理解,所以對這整個過程的記憶不太清楚,理解的也不太清楚。

面試官(笑了笑):你下去好好了解下吧。那你跟我談談事件委託吧。(第九個問題)

我(我再次無語,因為這個問題我之前也是在網上了解過,又特麼忘了!):給同屬於一類標籤元素新增一個click方法,就比如有十個li標籤,按照傳統的方式的話,是給每個標籤都加上一個onclick事件方法,但是這樣比較耗資源,事件委託就可以解決類似的事情。但是具體怎麼實現,我想想...搖了搖頭說暫時無法得知。

面試官(他又說了這一句話):你自己下去好好了解吧。那你跟我說說瀏覽器快取的問題吧,一般來說,使用者在請求一個檔案的時候,如果瀏覽器快取裡面有會從快取裡取,這樣就不用請求資料到伺服器了。這個原理是怎麼實現的?瀏覽器是怎麼判斷其快取裡是否有使用者請求的檔案,具體怎麼實現的?(第十問)

我(心裡一首涼涼送給自己):這個方面我沒了解過。

面試官:沒了解是吧?那好吧,我這邊暫時沒什麼問題了,你有什麼問題要問我的嗎?(第十一問)

我:您面了我這麼些時間,也知道我的能力所在,您是否有啥針對性建議我之後的學習呢?就比如我始終對前臺和後端之間的聯絡不太清楚,後臺的伺服器怎麼搭建,前臺通過什麼方式去取資料。

面試官:你可以自己搭建一個個人網站,自己親手程式設計實踐,從實踐中你就可以更加深入理解了。

我:好的,謝謝前輩。

完~~~

面試題:

一、自我介紹

二、做專案的時候用到了哪些基礎知識?

三、說說繼承並寫一個繼承程式碼

四、談談閉包

五、有沒有一種方法或者是方式可以實現外部函式能訪問到內部函式內的變數呢?

六、現在有一個實時更新的資料,要把這個資料展示在頁面,你怎麼實現?

七、使用者從地址輸入欄輸入網址回車到頁面展示的這個過程都發生了什麼?

八、談談事件委託

九、那你跟我說說瀏覽器快取的問題吧,一般來說,使用者在請求一個檔案的時候,如果瀏覽器快取裡面有會從快取裡取,這樣就不用請求資料到伺服器了。這個原理是怎麼實現的?瀏覽器是怎麼判斷其快取裡是否有使用者請求的檔案,具體怎麼實現的?

十、你有什麼問題要問我的嗎?

下面是我回去後自己整理的答案(1、2、10這是大家自己該做的準備,這裡不贅述):

三、說說繼承並寫一個繼承程式碼

答:繼承主要是依靠原型鏈來實現的。最常用的是組合繼承(借用建構函式和原型鏈組合繼承),繼承的方式還有原型式繼承、借用建構函式繼承、寄生式繼承、寄生組合式繼承。其次實現繼承還可以通過call()和apply()方法,call()和apply()方法是將this指向轉變成它們的第一個引數物件。

程式碼例項:

function Parent(){//建構函式Parent
    this.name = 'daddy';
}
Parent.prototype.sayName = function(){//建構函式Parent的原型物件上的方法sayName
    return this.name;
}
function Child(){//建構函式Child
    this.name = 'son';
}
Child.prototype = new Parent();//建構函式Child的原型物件是Parent
var parent = new Parent();//parent是建構函式Parent的一個例項
var child = new Child();//child是建構函式Child的一個例項
console.log(parent.sayName());//daddy,首先查詢自身,沒有sayName方法,就在其原型物件上查詢到了並呼叫
console.log(child.sayName());//son,自身沒有sayName方法,就去原型物件上查詢,它的原型物件是Parent,發現也沒有,就在Parent的原型物件上查詢到了

這裡面試官有可能會追問call()和apply()的使用方法和作用(參考連結:點選開啟連結

四、談談閉包

答:js高階程式設計第三版中給出的概念是:閉包是有權訪問其他函式內部變數的函式。

當你給出這個答案之後,你自己都會覺得這句話不足以讓面試官滿意,所以你還得進一步說明為什麼閉包能有權訪問其他函式內的變數呢?。

追答:由於在js中,變數作用域屬於函式作用域,在函式執行後作用域就會被清理,記憶體也隨之回收,但是由於閉包是建立在函式內部的子函式,它可訪問上級作用域(可理解為閉包快取了上級作用域),即使在外部函式執行完之後,外部函式的作用域也不會隨之銷燬(也就是其內部變數的值也不會銷燬),這時閉包就擁有了訪問上級作用域中變數的許可權。

但是,你還要做好準備,因為可能面試官會進一步追問。有可能他會問,閉包解決了什麼?

答:在本質上,閉包就是將函式內部和函式外部連線起來的一座橋樑。由於閉包可以快取上級作用域,那麼就使得函式外部打破了“函式作用域”的束縛,可以訪問函式內部的變數。以平時使用的ajax成功回撥為例,這裡其實就是一個閉包,由於上述的特性,回撥就擁有了整個上級作用域的訪問和操作能力,提高了極大的便利。開發者不用寫鉤子函式來操作上級作用域內部的變量了。

進一步可能會追問的問題,閉包有哪些應用場景?

答:閉包隨處可見,一個ajax請求的成功回撥,一個事件繫結的回撥方法,一個setTimeout的延時回撥,或者一個函式內部返回另一個匿名函式,這些都是閉包。簡而言之,無論使用何種方式對函式型別的值進行傳遞,當函式在別處被呼叫時都有閉包的身影。

剛才舉的例子是不是感覺好熟悉?有點像js非同步回撥裡的知識點(參考連結:點選開啟連結點選開啟連結

五、有沒有一種方法或者是方式可以實現外部函式能訪問到內部函式內的變數呢?

答:可以在函式內部建立一個閉包,在閉包內宣告一個變數,這個變數的值可以是靜值也可以動態變化,然後將該變數返回。最後在閉包外部,也就是外部函式的內部將閉包返回即可實現。

程式碼實現如下:

var bar = (function(){
    //這裡可以宣告外部函式的變數
    var foo = function (){
        var name = 'biubiu';
        return name;
    }
})();
console.log(bar());//biubiu

六、現在有一個實時更新的資料,要把這個資料展示在頁面,你怎麼實現?

答:(摘自知乎上的回答,連結:點選開啟連結

1,ajax短連線:客戶端每隔一秒鐘發一次請求,伺服器收到請求後會立刻返回結果,不管有沒有新資料。
2,ajax長連線:客戶端傳送一次請求,伺服器端收到請求後查詢有沒有新資料,如果沒有新資料就阻塞這個請求,直到有新資料或者超時為止。客戶端每次收到請求返回結果後立刻再發一次請求。comet貌似就是這個原理。
3,WebSocket:這就不是一個HTTP協議了,而是一個tcp協議,而且Socket這個玩意顧名思義就是一個流了,可以雙向操作。要想對webSocket有具體的瞭解,可以參考阮神的部落格,連結:點選開啟連結

對比延遲:
假設網路延遲是m毫秒,那麼ajax短連線的延遲在m到1000毫秒之間,另外兩種基本只有m毫秒的延遲。
對比資源佔用:
應該是1>2>3。但是1和2的比較要看情況,如果兩次請求間隔時間很長的話應該是2>1>3。

另外還有node.js的http://socket.io也可以實現。其次,回答完問題之後要隨時對面試官接下來的問題做好準備,因為他可能會追問關於ajax和WebSocket的相關知識。

七、使用者從地址輸入欄輸入網址回車到頁面展示的這個過程都發生了什麼?

答:這裡摘自一篇部落格,連結:點選開啟連結,不過可能一些概念沒講清楚,我個人推薦這篇部落格:點選開啟連結

對於網址欄的URL不同的操作方式有不同的載入資源、獲取資料的方式,下面的詳細過程針對"在位址列輸入URL,按enter(回車)鍵載入資源"此種操作方式做解析,其它的方式的過程大同小異,差異會在後面再做分析。

  1. 瀏覽器開啟一個執行緒來處理這個請求,對URL判斷如果是http協議就按照web方式處理;

  2. 瀏覽器先檢視瀏覽器快取-系統快取-路由器快取,如果快取中有,會直接在螢幕中顯示頁面內容(此時沒有向服務端發請求)。若沒有,則進行下一步操作(後面需要向服務端傳送請求);

  3. 通過DNS解析獲取網址的IP地址;

  4. 向真實IP地址伺服器發起tcp連線,與瀏覽器建立tcp三次握手。

  5. 握手成功後,進行HTTP協議會話,瀏覽器傳送報頭(請求報頭);

  6. 進入到web伺服器上的 Web Server,如 Apache、Tomcat、Node.JS 等伺服器;

  7. 進入部署好的後端應用,如 PHP、Java、JavaScript、Python 等,找到對應的請求處理;

  8. 處理結束回饋報頭,將資料返回至瀏覽器;

  9. 瀏覽器開始下載html文件(響應報頭,狀態碼200),同時設定快取;

  10. 之後瀏覽器對整個 HTML 結構進行解析,形成 DOM 樹;與此同時,它還需要對相應的 CSS 檔案進行解析,形成 CSS 樹(CSSOM)。    

       接下來,需要結合 DOM + CSSOM,形成一個繪製樹(Render Tree);

  11. 得到繪製樹之後,需要計算每個結點在頁面中的位置,這一個過程稱為layout ;

  12. layout的過程是在一個連續的二維平面上進行的,接下來,需要將這些結果柵格化,對映到螢幕的離散二維平面上,這一過  

       程稱為 paint ;  現代瀏覽器為提升效能,將頁面劃分多個 layer,各自進行 paint 然後組合成一個頁面(composite layers)。

PS: 開頭說到的"對於網址欄的URL不同的操作方式有不同的載入資源、獲取資料的方式"中其他方式的過程與上面方式差不多,只是在處理快取這一環節上有些不同:

1. “轉至”或位址列裡回車重新整理:見上

2. F5重新整理:沒有第2步,在第8步判斷返回值,如果返回304則表示有快取,且此時直接用快取;如果返回200則表示沒有快取,順序執行至最後

3. Ctrl+F5重新整理網頁的區別:沒有第2步,且在第8步一定返回200並順序執行至最後

(對於以上3種不同方式更好的應該從http協議的快取機制上做區分更容易理解,此處更側重'向服務端傳送請求及其返回值'這方面做一下區別)

八、談談事件委託

答:對“事件處理程式過多”問題的解決方案就是事件委託。事件委託利用了事件冒泡,只指定一個事件處理程式,就可以管理某一型別的所有事件。舉個例子就是假如我要實現分別點選十個不同的li標籤顯示不同的資訊,按照傳統的做法就是給每個li標籤新增一個事件處理程式,這樣很消耗資源,而且容易出現“空事件處理程式”,因為可能在某個時候會刪除某個li標籤,那麼對應的事件處理程式就是為空的,但是它依舊佔用了資源,有可能無法被視作垃圾進行回收。所以,這個時候利用事件委託就可以解決上面出現的問題。

根據不同面試官,他們的要求不一樣。有的面試官會聽你的理論解說是否有力,有的則是偏重你的程式碼能力。

程式碼實現:

HTML部分:

<ul id = 'mylists'>
    <li id='list-1'>go somewhere</li>
    <li id='list-2'>do something</li>
    <li id='list-3'>say some words</li>
</ul>

JS部分:

var list = document.getElementById('mylists');
list.addEventListener("click",function(e){
    if(e.target && e.target.nodeName == 'LI'){
        console.log('list',e.target.id.replace('list-',''),'was clicked!');
    }
});

九、那你跟我說說瀏覽器快取的問題吧,一般來說,使用者在請求一個檔案的時候,如果瀏覽器快取裡面有會從快取裡取,這樣就不用請求資料到伺服器了。這個原理是怎麼實現的?瀏覽器是怎麼判斷其快取裡是否有使用者請求的檔案,具體怎麼實現的?

在回答之前,我先說說這個問題到底怎麼答。這個問題你(如果你沒有對這方面的瞭解)起初聽完後會有點懵,面試官到底想從你身上獲取什麼資訊呢?是瀏覽器快取機制還是剛才後面追加的問題?很明顯的是,這題不管是快取機制和後面追加的問題,你都要答。但是不管怎麼說,這個問題你想答個七七八八,我想一個實習生的實力是很難做到的,這不是短時間內就能完全理解的知識點。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

補:

2018.11.04

現在回想起來,那時的自己真的不知道哪來的勇氣去面試騰訊,啥都不知道,很多基礎的知識點都不知道,比如常見的事件委託和http快取,但也正因為去了才知道自己是多麼的菜雞!

再來補充下秋招電面騰訊的問題(我筆試都沒過,只是後期有個部門招人就又把我的簡歷撿起來了,又虐我一遍,這次是真的"死透了"...):

秋招(問題不分順序)

一、自我介紹

二、你實習的時候專案使用的技術棧是什麼?有用過react麼?react和vue的區別是什麼?

三、http快取

四、TCP和UDP的區別

五、有了解過promise嗎?能說說它的原理是什麼嗎?

六、有了解過預載入和懶載入麼?它們的原理是什麼?

七、node有了解嗎?

八、js去重陣列有哪些方法?利用物件屬性去除的方法有什麼弊病?

九、如果後臺一次性給你返回上萬條資料,你怎麼進行處理才使得瀏覽器效能保持良好渲染?

十、async和await的原理是什麼?

十一、7:15在一個掛鐘上面顯示,時鐘和分鐘的夾角是多少度?

十二、let和const的區別是什麼?const建立一個物件之後為什麼還能修改其內的方法?它建立的原理是什麼?

十三、有使用過打包工具麼?gulp的工作原理是什麼?

十四、先有一個工作日誌系統(可跟蹤開發人員的程式碼使用率)需要你設計,你怎麼設計?

十五、有了解過現在前端的一些前沿技術麼?

十六、DNS的查詢步驟有哪些?

十七、判斷一個數據是否是陣列的方法有哪些?

至此,此次的面經分享完畢。總的來說,大公司的面試官要求應聘者的基礎知識牢固且知識體系廣。對於各個崗位的知識掌握度比較熟悉,而且一個常面的面試題在網上有很多,除開js高階程式設計第三版書中的各個內容,齊次就是網路優化和安全的問題。這兩大類考察的知識最多。其次就是你簡歷上寫的專案經驗和實習經歷,不管怎麼說,面經畢竟是別人的,自己獲取面經的經驗最佳途徑都是去面試,不要怕,在面試中成長是最快的,也很容易找到自己的不足之處。

現拿到三個offer,都是白菜價,結束了長達三個月的秋招,曾面試到一度否定自己,但是還是要保持好良好的心態,與君共勉。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

再更...

2018.11.23(沒聽清是哪個部門,反正在北京,騰訊體量太大了,到處在招人,當然了,我反正不優秀...)

一、js事件機制(瀏覽器在解析js檔案具體是怎麼樣的?瀏覽器怎麼判定非同步請求任務的順序?)

二、Promise、async和await

三、你怎麼設計封裝一個類似於Jquery的ajax請求?對於web要求的token機制你怎麼拿到後臺返回給你的token和怎麼判斷你拿到了?

四、瀏覽器具體是怎麼解析一個HTML模板的?

五、你在專案中有用到過哪些設計模式或自己研究過?

六、你在實習的過程中哪個專案你最驕傲或者哪個技術難道你攻克了?

七、你常用的js庫是什麼?說說vue的一些元件啊,UI啊等,你怎麼理解並應用到專案中的?