字節跳動前端一面面經

投遞初

春招過去了,面了兩次騰訊,兩次一面直接gg,但這兩份經歷對我是有很大幫助的,體會到了一定差距。但在6月份,看了牛客網討論區,又發現了字節跳動一直在招人,從未停止過,而且正好某天瞧見了內推碼,於是乎,我又想嘗試一下了,趕緊迭代一下簡歷,投!投!投!

要求

1、計算機、軟件相關專業;
2、熟悉HTML, CSS, JavaScript和HTTP協議基本知識;
3、熟悉常用的數據結構以及其使用場景;
4、有參與設計和實現的項目(無論大小);
5、瞭解瀏覽器調試工具;
6、有強烈的求知慾和進取心,具有紮實的編程功底,良好的編程習慣。

加分項:

1、有過數據可視化相關經驗;
2、瞭解JavaScript依賴管理;
3、瞭解Webpack, React, SASS, ES6基本原理以及它們解決的問題;
4、瞭解過不限於Node.js, Python, Ruby的任意一門腳本語言;
5、有Github賬號並有項目。

投遞完

不得不說,字節的處理效率真的是高,2號投的,3號就收到了HR小姐姐的電話詢問,簡單詢問做過什麼項目,用的是什麼技術棧,然後有沒有用過React,最後一句:如果後續簡歷通過了,我們會聯繫您進行面試。

然後再5號,下午還在做網絡安全的實驗,就收到微信消息,HR小姐姐加我然後跟我約下週面試時間。最後,選擇了8號(週一)晚上7點30約一面,話不多說,我們進入正題。

面經

自我介紹

熟悉的開頭,這裏就不多說了,跳過…

地址欄輸入url,然後經歷了什麼,瀏覽器此時又經歷了什麼

從URL輸入到頁面展現到底發生什麼?

推薦閱讀:從URL輸入到頁面展現到底發生什麼?

推薦閱讀:前端面試:http專場,你需要懂的知識

推薦閱讀:(建議精讀)HTTP靈魂之問,鞏固你的 HTTP 知識體系

瀏覽器解析渲染頁面

瀏覽器解析渲染頁面分爲一下五個步驟:

  • 根據 HTML 解析出 DOM 樹
  • 根據 CSS 解析生成 CSS 規則樹
  • 結合 DOM 樹和 CSS 規則樹,生成渲染樹
  • 根據渲染樹計算每一個節點的信息
  • 根據計算好的信息繪製頁面


推薦閱讀:從URL輸入到頁面展現到底發生什麼?

看了我的簡歷,說使用過Koa2,提出爲什麼要使用Koa2,怎麼不用express呢?

項目地址(傳送門)

Koa2中間件你瞭解過嘛?

項目中有提到用戶數據&狀態,然後問:你登錄攔截有具體瞭解怎麼實現的麼?

其實,面試官就是看到了這樣一句話:

瀏覽器發送一個 request 請求,根據 cookie ,服務器通過 passport 與 redis來驗證當前是否是登錄狀態,返回 username。

主要是項目忘了,我就提了一句用了passport中的一個函數,isAu…來着的,單詞不會讀

面試官也是覺得可能再問下去沒啥必要了,就說,我們來搞點基礎吧~

主要是三大模塊,CSS,JS,算法

考察CSS

css樣式優先級,以及渲染過程

  • 內聯樣式(例如, style="…")
  • ID選擇器(例如, #example)
  • 類選擇器(例如, .example)、屬性選擇器(例如, [type=“radio”])、僞類(例如, :hover)
  • 類型選擇器(例如, h1)、僞元素(例如, ::before)
  • 繼承的樣式

推薦閱讀:CSS 技巧篇(五):理解CSS優先級

下面樣式是怎樣渲染的

.container .inner div{
	width: 100px;
	height: 100px;
}

我說的是從右到左,這確實是沒有問題的,面試官反問,爲什麼? 其實道理很簡單,如果先渲染container,怎麼找inner呢?我說了全部遍歷一遍,然後又說了如果是從右到左的話,就會少一些查找。

下面代碼,父級元素container高度是多少?

<div class="container">
        <div class="inner"/>
        <div class="inner"/>
</div>

.container {
    border: 1px;
}
.inner {
    margin: 10px;
    height=width: 10px;
}

我自己重新寫了一個比較好理解的代碼,具體如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>    
    .container {
        border: 1px;
    }
    .inner1 {
        margin: 10px;
        height: 10px;
        width: 10px;
        background: red;
    }
    .inner2 {
        margin: 10px;
        height: 10px;
        width: 10px;
        background: blue;
    }
    </style>
</head>
<body>
    <div class="container">
        <div class="inner1"></div>
        <div class="inner2"></div>
    </div>
</body>
</html>

查看結果,高度爲50px

面試官然後又添加了浮動,再問父級元素高度

<div class="container">
        <div class="inner"/>
        <div class="inner"/>
</div>

.container {
    border: 1px;
}
.inner {
    float: left;
    margin: 10px;
    height=width: 10px;
}

查看結果,高度爲0px,此時就出現了一個高度塌陷問題。

因爲子元素設置了浮動,導致父級元素高度沒有算進去。通過以下方式即可清楚浮動,形成一個BFC,就會加上子集元素的高度。

.container {
    border: 1px;
    overflow: hidden;
}

重新打開開發者工具(F12),可以看到父級元素有了高度。

100px直徑的圓你怎麼畫?

推薦閱讀:趣味CSS3效果挑戰小彙總

推薦閱讀:css繪製特殊圖形

推薦:CSS3 border-radius圓角各個屬性值作用演示實例頁面

考察 JS

下面代碼會輸出什麼?(考察變量提升)

推薦閱讀:JavaScript變量提升運行機制

第一步
console.log(a);

此時會報錯,因爲a未定義。

第二步
console.log(a);
var a=1;

會輸出 undefined

上述代碼中,變量 avar 命令聲明,會發生變量提升,即腳本開始運行時,變量 a 已經存在了,但是沒有值,所以會輸出 undefined

第三步
console.log(a);
var a=1;
function a(){}

上述代碼會輸出一個函數 a

考察知識點:當有多個同名變量聲明的時候,函數聲明會覆蓋其他的聲明。如果有多個函數聲明,則是由最後的一個函數聲明覆蓋之前所有的聲明。

第四步
console.log(a);
var a=1;
function a(){}
a=2;

上述代碼結果與知識點與 第三步 一樣

第五步
console.log(a);
var a=1;
function a(){}
a=2;
a();

推薦閱讀:javascript變量提升詳解
推薦閱讀:深入淺出JS - 變量提升(函數聲明提升)

輸出結果:

上述代碼,首先進行函數聲明提升,然後再進行變量提升,此時 a已經是一個變量了,不再是一個函數了,所以就會 throw error

下面代碼會輸出什麼?(考察事件循環)

推薦閱讀:Javascript 事件循環event loop

第一步
setTimeout(() => {
    console.log(1)
},0);
console.log(2)
// 輸出結果:2 1
第二步
setTimeout(() => {
    console.log(1)
},0);
console.log(2)
new Promise((resolve) => {
    console.log(3);
    resolve(4)
}).then(val => console.log(val))
// 輸出結果:2 3 4 1
第三步
document.body.addEventListener('click', () => {
Promise.resolve().then(() => console.log(1))
console.log(2);
}, false)

document.body.addEventListener('click', () => {
Promise.resolve().then(() => console.log(3))
console.log(4);
}, false)

之前那幾題答完後,這道題,我毫不猶豫的直接說了 2 4 1 3 ,然後面試官給了我下面這代碼提示,啪,直接被拍醒…

document.body.click()


後面搜了相關資料,原來是設計模式中的發佈-訂閱模式,之前就看了面經,知道字節喜歡考這個設計模式,原來真的又考到了,不過題型不一樣罷了。

推薦閱讀:Javascript設計模式之發佈-訂閱模式

推薦閱讀:前端JavaScript的發佈-訂閱模式

算法題

你瞭解迴文字符串嗎?例如abba,寫一下代碼吧(不限語言)

#include<bits/stdc++.h>
using namespace std;
int main(){
    string str;
    cin>>str;
    int len=str.length();
    int mid=(len+1)/2;
    string ans1=str.substr(0,mid); //取前半段字符串
    if(len&1) mid--;
    string ans2=str.substr(mid,len-mid); //取後半段字符串
    reverse(ans2.begin(),ans2.end()); //取反
    if(ans1==ans2) cout<<1<<endl;
    else cout<<0<<endl;
    return 0;
}

由於不限語言,我就用了 C++ 編寫了,當時忘記對第二個字符串取反了,也沒有驗證是否可行,就直接上代碼了

那你可以求出字符串中最長迴文子串嗎?例如給你abbac,得到abba

我當時提到了馬拉車算法(Manacher),面試官要我手寫一下,還是吃了過去的虧啊,打比賽還遇到過,沒有怎麼使用就忘了,今天又重新溫習一下吧…

話不多說,先貼參考博客:

推薦閱讀:馬拉車算法(Manacher’s Algorithm)

貼上代碼:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int maxn=1e3+5;
int p[maxn];
int main(){
    string str;
    while(cin>>str){
        string s="$";//第一步:預處理,將原字符串轉換爲新字符串
        for(int i=0;i<str.length();i++)
            s+="#",s+=str[i];
        s+="#@"; //尾部再加上字符@,將偶數長度變爲奇數長度
        int n=s.length();
        int id=0,mx=0; //初始化中心位置和最右端位置
        int maxlen=-1,idx=0;
        for(int j=1;j<n-1;j++){
            p[j]=mx>j? min(p[2*id-j],mx-j):1;
            while(s.at(j+p[j]) == s.at(j-p[j])) //向左右兩邊拓展
                p[j]++;
            if(mx<p[j]+j){ //如果超過右邊界,進行更新
                mx=p[j]+j;
                id=j;
            }
            if(maxlen<p[j]-1){ //更新最大長度和中心索引位置
                maxlen=p[j]-1;
                idx=j;
            }
        }
        int start=(idx-maxlen)/2;  //求起始點索引
        string ans=str.substr(start,maxlen); //字符串截取得到最長迴文子串
        cout<<ans<<endl;
    }
    return 0;
}

用兩種數據,進行測試,得到如下結果:

總結

每次面完之後,都要好好總結一下。當我寫完這篇文章之後,我發現本次面試難度算很低了,沒有考察要你手撕各種設計模式,還有手撕 Promise、手撕 new等等。這些我在面試前還做了準備,但是我發現我又遺忘了…原因很簡單,只是第一次接觸那些手撕,用的也不是很多,還有更多的知識也是在面試前搶記的。看的特別廣而雜,反而知識沒有連通性,記着記着自然遺忘了。

其次,對於字節跳動,經歷過這一次面試後,我也逐漸發現面試都差不多,面試官都挺好的,期間還會暗示你(當然你懂他意思的話…),面之前,一看是頭條我一下覺得沒啥自信了,都說頭條很在意算法,但本次考察的算法好像沒有 acm 那樣的難度,而是自己把自己給嚇住了,信心自然沒了…

過了好幾天了,也沒有收到感謝信,當然,也沒有收到下次面試通知,估計是 “入庫” 了吧,在此,寫下今後的安排:

  • 無需懼怕算法題,難度真的沒有 acm 那個高度
  • 將知識重新撿起來,不要在要面試的時候,才臨時搶記知識
  • 安靜地努力,每篇文章寫完後就要消化,不要沒弄懂就發佈
  • 文章不在於多,而在於精,將每篇文章都要認真書寫,讓讀者都能一讀即懂

發現每次只有把知識點講出來纔會印象深刻,今後的日子也要這樣做!

最後,本次面經書寫完畢,算是一次不錯的體驗了,還要繼續加油~

更多前端知識內容,可以訪問我的筆記倉庫:https://yangchaoyi.vip/

製作不易,留下您的點贊 和 star,就是對我的支持啦~

學如逆水行舟,不進則退
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章