寫在開頭
大家好,這裏是lionLoveVue,基礎知識決定了編程思維,學如逆水行舟,不進則退。金三銀四,爲了面試也還在慢慢積累知識,Github上面可以直接查看所有前端知識點梳理,github傳送門,覺得不錯,點個Star★,好運連連,Offer終究鼠於你,持續更新中。另外,也可以關注微信公衆號:小獅子前端Vue,源碼以及資料今後都會放在裏面。
一直想着成爲一個up主,正值時間挺多的,4月份左右面試的面經我會製作視頻去分享,趕快捧個場吧。嗶哩嗶哩:一百個Chocolate
文章目錄
面試準備——自我介紹
一面 / 二面
面試技巧
- 準備要充分
- 知識要系統
- 溝通要簡潔
- 內心要誠實
- 態度要謙虛
- 回答要靈活
頁面佈局
題目
假設高度已知,請寫出三欄佈局,其中左、右欄寬度各爲300px,中間自適應
五種解決方式代碼
- 浮動解決方式
- 絕對定位解決方式
- flexbox解決方式
- 表格佈局
- 網格佈局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Layout</title>
<style>
html *{
padding: 0;
margin: 0;
}
.layout{
margin-top: 20px;
}
.layout article div{
min-height: 100px;
}
</style>
</head>
<body>
<!-- 浮動解決方式 -->
<section class="layout float">
<style>
.layout.float .left{
float: left;
width: 300px;
background: red;
}
.layout.float .right{
float: right;
width: 300px;
background: blue;
}
.layout.float .center{
background: yellow;
}
</style>
<article class="left-right-center">
<div class="left"></div>
<div class="right"></div>
<div class="center">
<h1>浮動解決方式</h1>
1.這是三欄佈局的正中間部分
2.這是三欄佈局的正中間部分
</div>
</article>
</section>
<!-- 絕對定位解決方式 -->
<section class="layout absolute">
<style>
.layout.absolute .left-center-right>div{
position: absolute;
}
.layout.absolute .left{
left: 0;
width: 300px;
background: red;
}
.layout.absolute .center{
left: 300px;
right: 300px;
background: yellow;
}
.layout.absolute .right{
right: 0;
width: 300px;
background: blue;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>絕對定位解決方式</h1>
1.這是三欄佈局的正中間部分
2.這是三欄佈局的正中間部分
</div>
<div class="right"></div>
</article>
</section>
<!-- flexbox解決方式 -->
<section class="layout flexbox">
<style>
.layout.flexbox{
margin-top: 140px;
}
.layout.flexbox .left-center-right{
display: flex;
}
.layout.flexbox .left{
width: 300px;
background: red;
}
.layout.flexbox .center{
flex: 1;
background: yellow;
}
.layout.flexbox .right{
width: 300px;
background: blue;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>flexbox解決方式</h1>
1.這是三欄佈局的正中間部分
2.這是三欄佈局的正中間部分
</div>
<div class="right"></div>
</article>
</section>
<!-- 表格佈局 -->
<section class="layout table">
<style>
.layout.table .left-center-right{
width: 100%;
display: table;
height: 100px;
}
.layout.table .left-center-right>div{
display: table-cell;
}
.layout.table .left{
width: 300px;
background: red;
}
.layout.table .center{
background: yellow;
}
.layout.table .right{
width: 300px;
background: blue;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>表格解決方式</h1>
1.這是三欄佈局的正中間部分
2.這是三欄佈局的正中間部分
</div>
<div class="right"></div>
</article>
</section>
<!-- 網格佈局 -->
<section class="layout grid">
<style>
.layout.grid .left-center-right{
display: grid;
width: 100%;
grid-template-rows: 100px;
grid-template-columns: 300px auto 300px;
}
.layout.grid .left{
background: red;
}
.layout.grid .center{
background: yellow;
}
.layout.grid .right{
background: blue;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>網格解決方式</h1>
1.這是三欄佈局的正中間部分
2.這是三欄佈局的正中間部分
</div>
<div class="right"></div>
</article>
</section>
</body>
</html>
展示效果
知識拓展
上述5中解決方式是比較常見的,但是我們不能只侷限於爲了問答而問答,我們應該從此基礎上升華一下問題。
答完了這5種常見方式,並不代表我們頁面佈局這一話題就結束了,面試官可能還會延伸我們的問題,比如:
- 這5種佈局方式各自有什麼優點和缺點?
- 如果
高度已知
條件去掉,考慮縱向,那麼對於中間內容過多,導致中間格子撐開,此時需要左右跟着撐開,以上5種方式哪幾種還能使用? - 這5中方式的兼容性如何?如果讓你選擇一種最優的去應用於業務,你會選擇哪種方式?
那麼,接下來就來圍繞這三個問題來講解:
1、各自的優缺點
① 對於浮動:
優點
兼容性比較好,把清除浮動和其它浮動周邊元素的關係處理好的話,那麼它的兼容性是挺不錯的。
缺點
設置浮動之後,脫離了文檔流,處理不好的話,會帶來很多問題,這是它本身的侷限性。
② 對於絕對定位:
優點
快捷,不容易出問題
缺點
本身脫離了文檔流,就會導致子元素跟着脫離文檔流。因此,導致絕對定位的有效性
、可使用性
比較差。
③ 對於flexbox
css3中推出的flex佈局,就是爲了解決上述兩種方式不足而出現的,算是比較完美的一種方式,尤其是對於移動端
④ 對於表格佈局
優點
儘管多數人吐槽表格佈局,但其實,表格佈局在很多場景都適用的。比如上文寫的三欄佈局設計當中,表格佈局是不是很輕鬆就實現了呢?
同時,表格佈局的兼容性是非常好的,當用flex
解決不了問題的時候,對於PC端 IE8
是不支持flex
的,此時就可以嘗試表格佈局
缺點
除開歷史上一些詬病外,還有一個:
比如我們把三欄理解成爲三個小單元格,那麼當其中某一個單元格高度超出的時候,其餘兩側也會跟着調整,於是對於有些場景是不合適的。因此,對於不同場景,我們可以在flex
和表格
佈局進行選優操作
⑤ 對於網格佈局
這一塊的話,算是新熱點,也是經歷了一段時間的演變,從上文代碼來看的話,通過網格佈局我們能讓代碼更加簡單、方便實現邏輯。在面試的時候提到也可以說明你比較關注新的事物,主動學習能力不錯。
當然,以上表述有部分個人思考,也有現常說的優缺點,讀者可以根據研究佈局方式進行深入思考,學習更多的使用場景以及優缺點,其次,歡迎提出新的解決方案及相關知識點,後續進行補充。
2、去掉高度,有哪幾種佈局可以使用?
這裏,我們就採用增加高度方式來看看,還有哪些佈局能使用。(中間區域增加幾個p標籤)
源代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Layout</title>
<style>
html *{
padding: 0;
margin: 0;
}
.layout{
margin-top: 20px;
}
.layout article div{
min-height: 100px;
}
</style>
</head>
<body>
<!-- 浮動解決方式 -->
<section class="layout float">
<style>
.layout.float .left{
float: left;
width: 300px;
background: red;
}
.layout.float .right{
float: right;
width: 300px;
background: blue;
}
.layout.float .center{
background: yellow;
}
</style>
<article class="left-right-center">
<div class="left"></div>
<div class="right"></div>
<div class="center">
<h1>浮動解決方式</h1>
1.這是三欄佈局的正中間部分
2.這是三欄佈局的正中間部分
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
</div>
</article>
</section>
<!-- 絕對定位解決方式 -->
<section class="layout absolute">
<style>
.layout.absolute .left-center-right>div{
position: absolute;
}
.layout.absolute .left{
left: 0;
width: 300px;
background: red;
}
.layout.absolute .center{
left: 300px;
right: 300px;
background: yellow;
}
.layout.absolute .right{
right: 0;
width: 300px;
background: blue;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>絕對定位解決方式</h1>
1.這是三欄佈局的正中間部分
2.這是三欄佈局的正中間部分
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
</div>
<div class="right"></div>
</article>
</section>
<!-- flexbox解決方式 -->
<section class="layout flexbox">
<style>
.layout.flexbox{
margin-top: 140px;
}
.layout.flexbox .left-center-right{
display: flex;
}
.layout.flexbox .left{
width: 300px;
background: red;
}
.layout.flexbox .center{
flex: 1;
background: yellow;
}
.layout.flexbox .right{
width: 300px;
background: blue;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>flexbox解決方式</h1>
1.這是三欄佈局的正中間部分
2.這是三欄佈局的正中間部分
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
</div>
<div class="right"></div>
</article>
</section>
<!-- 表格佈局 -->
<section class="layout table">
<style>
.layout.table .left-center-right{
width: 100%;
display: table;
height: 100px;
}
.layout.table .left-center-right>div{
display: table-cell;
}
.layout.table .left{
width: 300px;
background: red;
}
.layout.table .center{
background: yellow;
}
.layout.table .right{
width: 300px;
background: blue;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>表格解決方式</h1>
1.這是三欄佈局的正中間部分
2.這是三欄佈局的正中間部分
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
</div>
<div class="right"></div>
</article>
</section>
<!-- 網格佈局 -->
<section class="layout grid">
<style>
.layout.grid .left-center-right{
display: grid;
width: 100%;
grid-template-rows: 100px;
grid-template-columns: 300px auto 300px;
}
.layout.grid .left{
background: red;
}
.layout.grid .center{
background: yellow;
}
.layout.grid .right{
background: blue;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>網格解決方式</h1>
1.這是三欄佈局的正中間部分
2.這是三欄佈局的正中間部分
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
<p>增加高度</p>
</div>
<div class="right"></div>
</article>
</section>
</body>
</html>
展示效果
這裏,圖片可能不是特別清楚,讀者可以跑一遍上述代碼,在瀏覽器打開使用會更好一點嗷~
總結
從上述顯示效果來看的話,改變了高度,用flex
和表格
佈局還能繼續使用。
對於第一塊,也就是浮動佈局那一塊,我們還可以進行知識拓展:
-
爲什麼會有兩段文字跑到最左邊去了呢?
答:因爲向左浮動的原因,上面文字被左邊紅色部分擋住了,當內容超過高度後,就會往左邊移動了。
-
那你怎麼將多餘的兩段文字接着上述文字顯示,而不是向左移動?
答:這就扯到了BFC的問題,清楚浮動等等,這裏就不再進行拓展了,不然這篇文章沒法完結啦。。。
頁面佈局模塊——總結
- 語義化掌握到位
- 頁面佈局深刻理解
- CSS基礎紮實
- 思維靈活且積極上進
- 代碼書寫規範
頁面佈局的變通
三欄佈局
- 左右寬度固定,中間自適應
- 上下高度固定,中間自適應
兩欄佈局
- 左寬度固定,右自適應
- 右寬度固定,左自適應
- 上寬度固定,下自適應
- 下寬度固定,上自適應
CSS盒模型
題目
談談你對CSS盒模型的認識
-
基本概念:標準模型+IE模型
-
標準模型和IE模型的區別
-
CSS如何設置這兩種盒模型
-
JS如何設置獲取盒模型對應的寬和高
-
實例題(根據盒模型解釋邊距重疊)
-
BFC(邊距重疊解決方案)
以上內容知識點由淺入深,知識點理論從CSS->JS->CSS
基本概念
標準盒模型、怪異盒模型(IE盒模型)和flex彈性伸縮盒模型以及多列布局
- 標準盒模型(box-sizing content-box)
- IE盒模型(box-sizing border-box)
content = width+padding+border
附完美回答方式:
標準盒子模型,即box-sizing content-box,瀏覽器默認模型,我們所寫的width和height並不是最終盒子的寬高,而是content的,盒子的寬高由我們的content+padding+border來組成的,但是這樣在做項目時可能會遇到小問題,假如我想構建一個100x100的盒子大小,但是我發現我寫的是width和height是100,於是我需要加上padding及border,但是加上去之後,盒子也會相應變大,這就造成改動麻煩。
後面css3中提供了IE盒子模型,能夠直接控制盒子的大小。於是項目中大多數用上了IE盒子模型,以及我看過bootstrap以及element-ui源碼中大部分也是用的IE盒子模型
以上回答方式,請讀者可以好好體會一下,挖掘其中的亮點!
- FLEX盒模型
關於這裏可以參考阮一峯老師的文章
- 多列布局(基本上不用)
讀者可以適當瞭解一下,這裏就不加以說明了
JS如何獲取盒模型對應的寬和高
①dom.style.width / height
這種方法,有一定侷限性,只能取內聯樣式的寬高。
②dom.currentStyle.width / height
這種方法,也是有一定侷限性,不過我們三種常用css樣式都能獲取。但是隻支持IE
,其它瀏覽器不支持
③ window.getComputedStyle(dom).width / height
支持所有瀏覽器,兼容性好
④ dom.getBoundingClientRect().width / height
這種方法,一般用於計算元素的絕對位置,根據視窗左上角的點來算的。可以拿到四個元素值:left
、top
、width
、height
實例題(根據盒模型解釋邊距重疊)
如下圖,有兩個盒子,深色的定爲父元素,淺色的定位子元素,子元素的高度爲100px
,與父元素的上邊距爲10px
,請問父元素實際高度是多少?
結合這個標題的情況,你可能會說是100px,但你也可能就是直接相加,覺得是110px,但都不是面試官覺得滿意的回答,因爲要看父元素的盒模型是如何設置的,下面來探討這個問題:
我們在界面裏來寫一個父子元素的盒子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS盒模型</title>
<style>
html *{
padding: 0%;
margin: 0;
}
</style>
</head>
<body>
<section id="sec">
<style>
#sec{
background: #f00;
}
.children{
height: 100px;
margin-top: 10px;
background: yellow;
}
</style>
<article class="children">
</article>
</section>
</body>
</html>
打開瀏覽器,出現如下界面:
我們父級元素貌似沒看到,打開開發者工具(按下F12
)
此時,我們看一下計算屬性 Computed
發現,此時高度是100px
。
同時,我們也看一下子元素的高度,如下,也是100px
。
那是不是就是100px
呢?在回答之前,接着來如下操作,我們修改一個地方:
在父元素樣式裏設置 overflow: hidden;
此時,我們再次查看content,變成了110px
。
此時,就有疑問了,爲什麼之前是100px
,而當我們加了overflow: hidden;
之後變成了110px
了呢?
補充知識點:
我們常見的邊距重疊,有兩種情況:
- 父子元素重疊(如上文所述)
- 兄弟之間重疊:比如兩個格子,第一個格子下邊距30px,第二個上邊距5px,會取一個最大值30px作爲邊距。另外,特殊一點的就是空元素了,會取
margin-top
和margin-bottom
的最大值
補充完後,接着回答上一個問題,爲什麼加了overflow: hidden;
之後變成了110px
了呢?
其實,是給父級元素創建了一個BFC
,這裏我們在下文繼續討論。
BFC(邊距重疊解決方案)
BFC基本概念:塊級格式化上下文
與之並列的一個是IFC(內聯格式化上下文)這個不常考,就提一下。
BFC的原理(渲染規則)
① 在BFC這個元素的垂直方向
邊距會發生重疊
② BFC的區域不會與浮動元素的box重疊,可用來清除
浮動佈局
③ BFC是一個獨立
的容器,外面的元素不會影響裏面的元素,同時,裏面的元素不會影響外面的元素。
④ 計算BFC元素高度的時候,浮動元素也會參與計算
怎麼創建BFC?
① float
值不爲none,因爲CSS默認爲none,只要設置了浮動,當前元素就設置了BFC
② static:靜態定位。它是position
的默認值,一般不設置position屬性時,元素會按照正常的文檔流進行排列。那麼,只要position不爲默認值static也是設置了BFC
③ display
屬性,table、table-cell等table相關的,都是設置了BFC
④ overflow
: auto / hidden
BFC使用場景
垂直方向邊距重疊問題
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS盒模型</title>
<style>
html *{
padding: 0%;
margin: 0;
}
</style>
</head>
<body>
<section id="sec">
<style>
#sec{
background: #f00;
}
.children{
height: 100px;
margin-top: 10px;
background: yellow;
}
</style>
<article class="children">
</article>
</section>
<!-- BFC垂直方向邊距重疊 -->
<section id="margin">
<style>
#margin{
background: pink;
overflow: hidden;
}
#margin>p{
margin: 5px auto 25px;
background: red;
}
</style>
<p>a</p>
<p>b</p>
<p>c</p>
</section>
</body>
</html>
如下圖所示,a的頂部只有5px,而b的頂部用到了a的底部25px,因此就造成了邊距重疊問題
如何消除上述情況?
給子元素創建父元素,讓父元素設置BFC
如下圖所示,僅需加一個div,然後設置overflow: hidden
即可
效果
接下來,來一個左邊固定,右邊自適應的例子。
<!-- BFC不予float重疊 -->
<section id="layout">
<style>
#layout{
margin-top: 10px;
background: red;
}
#layout .left{
float: left;
width: 100px;
height: 100px;
background: pink;
}
#layout .right{
height: 110px;
background: #ccc;
}
</style>
<div class="left"></div>
<div class="right"></div>
</section>
效果
從上圖可以看到,右邊因爲寬度設置的高一點,經過浮動重疊到了左邊一部分,此時,我們僅需一行代碼即可overflow: auto;
#layout .right{
height: 110px;
background: #ccc;
overflow: auto;
}
效果
計算BFC元素高度的時候,浮動元素也會參與計算
怎麼理解這個概念呢?比如下面代碼:
<!-- BFC子元素即使是float也會參與高度計算 -->
<section id="float">
<style>
#float{
background: green;
}
#float .float{
float: left;
font-size: 30px;
}
</style>
<div class="float">I am 浮動元素</div>
</section>
效果
我們從上面圖片發現,沒有父級元素,於是檢查一下,發現父級高度爲0,因爲子元素設置了浮動,高度沒有算進去
解決辦法,父級元素設置清除浮動,於是形成了一個BFC,然後就會加上子級元素的高度
#float{
background: green;
overflow: hidden;
}
從門再次打開開發者工具(F12),可以看到,父級元素已經有了高度
DOM 事件類
題目
-
基本概念:DOM事件的級別
-
DOM事件模型
-
DOM事件流
-
描述DOM事件捕獲的具體流程
-
Event對象的常見應用
-
自定義事件
基本概念:DOM事件的級別
DMO事件類 | 事件級別 |
---|---|
DOM0 | element.οnclick=function(){} |
DOM2 | element.addEventListener(‘click’, function(){} , false) |
DOM3 | element.addEventListener(‘keyup’, function(){} , false) |
爲啥沒有DOM1呢?
答:因爲DOM1制定的時候,沒有設計與事件相關的東西,但不代表DOM1標準不存在
DOM3也是一種事件定義方式,相對來說事件類型增加了,比如鼠標鍵盤事件等
最後一個boolean
值表示事件模型是捕獲還是冒泡,默認爲false
冒泡,爲true
表示捕獲。
DOM事件模型
分爲捕獲(從上到下)和冒泡(從目標元素往上)
DOM事件流
如上圖所示,這就是一個事件流,一個完整的事件流
分爲三個階段:
- 第一階段是捕獲
- 第二階段是目標階段,比如說點按鈕就是目標階段,或者說是事件通過捕獲到達目標元素
- 第三階段是從目標元素上傳到window對象,也就是冒泡的過程
描述DOM事件捕獲的具體流程
(冒泡方向與之相反)
Event對象的常見應用
event.preventDefault()
(阻止默認,例如鏈接等)event.stopPropagation()
(阻止冒泡)event.stopImmediateProgation()
(事件響應優先級,例如給一個按鈕添加兩個事件A和B,你想要只執行A,不執行B,就在A的響應函數裏添加這個方法,就會阻止B事件的執行)event.currentTarget
(表示當前所綁定的事件,如下面所述,指向的就是父級元素)event.target
(與事件委託相關,把子元素的事件全都轉到父級元素上,進行優化,只需綁定一次事件,然而作響應的時候,需要區別是哪個子元素被點擊,該方法就可以綁定當前被點擊的元素)
自定義事件
var eve = new Event('custome');
ev.addEventListener('custome',function(){
console.log('custome');
});
ev.dispatchEvent(eve);
CustomEvent
是爲了解決Event事件不能傳數據的問題
實例分析
上文講述了相關知識點,下面我們通過代碼來簡單實現,讓抽象的知識更加具體化
DOM事件捕獲的具體流程實例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="ev">
<style>
#ev{
width: 300px;
height: 100px;
color: #fff;
text-align: center;
line-height: 100px;
background: red;
}
</style>
目標元素
<script type="text/javascript">
var ev=document.getElementById('ev');
//DOM2中定義事件 window
window.addEventListener('click',function(){
console.log('window capture')
},true)
//document
document.addEventListener('click',function(){
console.log('document capture')
},true)
//html
document.documentElement.addEventListener('click',function(){
console.log('html capture')
},true)
//body
document.body.addEventListener('click',function(){
console.log('body capture')
},true)
//目標元素
ev.addEventListener('click',function(){
console.log('ev capture')
},true)
/* 自定義事件 */
var eve = new Event('test');
ev.addEventListener('test',function(){
console.log('test dispatch')
},true)
setTimeout(function(){
ev.dispatchEvent(eve);
},2000)
</script>
</div>
</body>
</html>
效果
HTTP 協議類
題目
-
HTTP協議的主要特點
-
HTTP報文的組成部分
-
HTTP方法
-
POST和GET的區別
-
HTTP狀態碼
-
什麼是持久連接
-
什麼是管線化
HTTP協議的主要特點
- 簡單快速 (每個資源URL是固定的,一個圖片或頁面地址,統一資源符,只需輸入URL即可訪問)
- 靈活 (在HTTP協議頭部head部分有一個數據類型,通過http協議可以完成不同數據類型的傳輸)
- 無連接 (連接一次會斷掉,不會保持連接)
- 無狀態 (客戶端和服務端連接兩次,不能區分兩次連接者身份)
HTTP報文的組成部分
- 請求行:包含方法、頁面地址、HTTP協議版本
- 請求頭:key-value值,告訴服務端需要什麼內容,要注意什麼類型
- 空行:告訴服務端請求頭結束,接下來是請求體部分了
- 請求體:數據部分
同理,響應報文
請求示例
以上第一行就是請求行,包含GET
方法 / 表示首頁 HTTP/1.1
表示HTTP協議版本
後面內容都是請求頭,都是key-value
鍵值對
空行在這裏沒有顯示出來,然後對於請求體就是一些數據部分了。
響應示例
第一行是狀態行,包含HTTP協議版本,協議狀態碼200
下面就是響應頭了,也是鍵值對的形式
下面會有一個空行,類似下面這種效果(下面這條分割橫線)
HTTP方法
方法 | 作用 |
---|---|
GET | 獲取資源 |
POST | 傳輸資源 |
PUT | 更新資源 |
DELETE | 刪除資源 |
HEAD | 獲取報文首部 |
POST和GET的區別(重點前5條)
-
get在瀏覽器回退時是無害的,而post會再次提交請求
-
get請求會被瀏覽器主動緩存,而post不會,除非手動設置
-
get請求參數會被完整保留在瀏覽器歷史記錄裏,而post中的參數不會被保留
-
get請求在URL中傳送的參數是有長度限制的,而POST沒有限制
-
get參數通過URL傳遞,post放在Request body中
-
get請求只能進行url編碼,而post支持多種編碼方式
-
對參數的數據類型,get只接受ASCALL字符,而post沒有限制
-
get比post更不安全,因爲參數直接暴露在URL上,所以不能用來傳遞敏感信息
-
get產生的URL地址可以被收藏,而post不可以
HTTP狀態碼
- 1xx:指示信息——表示請求已接收,繼續處理
- 2xx:成功——表示請求已經被成功接收
- 3xx:重定向——要完成請求必須進行更進一步的操作
- 4xx:客戶端錯誤——請求有語法錯誤或請求無法實現
- 5xx:服務器錯誤——服務器未能實現合法的請求
一般答完上述基本ok了,如果問的詳細一點的話,就多加一點知識上去:
200 OK
:客戶端請求成功206 Partial Content
:客戶發送了一個帶有Range(範圍)頭的GET請求,服務器完成了它(比如客戶端請求0-1w字節,服務器就會返回206,常見播放視頻和音頻地址,文件過大時一般返回206)
301 Moved Permanently
:所請求的頁面已經轉移至新的URL302 Found
:所請求的頁面已經臨時
轉移至新的URL304 Not Modified
:客戶端有緩衝
的文檔併發出一個條件性的請求,服務器告訴客戶,原來緩衝的文檔還可以繼續使用
400 Bad Request
:客戶端請求有語法錯誤,不能被服務器所理解401 Unauthorized
:請求未經授權,這個狀態碼必須和WWW-Authenticate
報頭域一起使用403 Forbidden
:請求訪問的頁面被禁止(比如頁面只能通過服務端去訪問)404 Not Found
:請求資源不存在
500 Internal Server Error
:服務器發生不可預料的錯誤但原來緩衝的文檔還可以繼續使用503 Server Unavailable
:請求未完成,服務器臨時過載或當機,一段時候後可能恢復正常
什麼是持久連接
HTTP協議採用“請求-應答”模式,當使用普通模式,即非 Keep-Alive
模式時,每個請求 / 應答客戶和服務器都要新建一個連接,完成之後立即斷開連接(HTTP協議爲無連接的協議)
當使用 Keep-Alive
模式(又稱持久連接、連接重用)時,Keep-Alive
功能使客戶端到服務端的連接持續有效,當出現對服務器的後續請求時,Keep-Alive
功能避免了建立或者重新建立連接
PS:只有HTTP 1.1 版本才支持持久連接,1.0不支持。
什麼是管線化(加分點)
在使用持久連接的情況下,某個連接上消息的傳遞類似於
請求1->響應1->請求2->響應2->請求3->響應3
某個連接上的消息類似變成了這樣:
請求1->請求2->請求3->響應1->響應2->響應3
(將請求打包一起發送,然後服務器一起打包回來響應)
拓展知識:
- 管線化機制通過持久連接完成,僅
HTTP / 1.1
支持此技術(重點) - 只有
get
和head
請求可以進行管線化,而post
有所限制(重點) - 初次創建連接時不應啓動管線機制,因爲對方(服務器)不一定支持
HTTP /1.1
版本的協議(重點) - 管線化不會影響響應到來的順序,如上面的例子所示,響應返回的順序並未改變
HTTP / 1.1
要求服務器端支持管線化,但並不要求服務器端也對響應進行管線化處理,只是要求對於管線化的請求不失敗即可- 由於上面提到的服務器端的問題,開啓管線化很可能並不會帶來大幅度的性能提升,而且很多服務器端和代理程序對管線化的支持並不好,因此現代瀏覽器如
Chrome
和Firefox
默認並未開啓管線化支持
原型鏈
題目
- 創建對象有幾種方法
- 原型、構造函數、實例、原型鏈
- instanceof的原理
- new運算符
創建對象有幾種方法
var o1 = {name:'o1'};
var o11 = new Object({name:'o11'});
var M = function(){this.name='o2'};
var o2 = new M();
var P = {name:'o3'};
var o3 = Object.create(P);
原型、構造函數、實例、原型鏈
var M = function(name){this.name=name}; //構造函數
var o2 = new M('o2'); //實例
構造函數和原型對象的關係
實例和構造函數的關係
原型鏈:通過原型鏈的方式,找到原型對象,原型對象的方法是被不同實例所共有的。例如Object上有toString()方法,因此其它所有的實例都共有這個方法。
instanceof的原理
instanceof
原理就是判斷當前實例是不是當前構造函數的實例對象,判斷依據就是實例對象的__proto__
和構造函數的prototype
是否指向相同的引用,只要在一條原型鏈上,instanceof
就會返回true
。
很抽象是吧,下面我們還是舉上文的例子:
var M = function(name){this.name=name};
var o2 = new M('o2');
因此,instanceof
判斷不嚴謹,比如m繼承了a、b、c,我怎麼判斷是繼承了哪一個呢?用instanceof
判斷都返回true
。
下面就來,介紹constructor
判斷方式
new運算符
-
一個新對象被創建。它繼承自
foo.prototype
-
構造函數foo被執行。執行的時候,相應的參數會被傳入,同時上下文(this)會被指定爲這個新實例。
new foo
等同於new foo()
,只能用在不傳遞任何參數的情況 -
如果構造函數返回一個“對象”,那麼這個對象會取代整個new出來的結果。如果構造函數沒有返回對象,那麼new出來的結果爲步驟1創建的對象
面向對象
題目
類與實例
- 類的聲明
- 生成實例
類與繼承
- 如何實現繼承
- 繼承的幾種方式
類與實例
<body>
<script>
/* 類的聲明 */
function Animal(){
this.name='aaa';
}
/* ES6中的class的聲明 */
class Animal2{
constructor(){
this.name = 'bbb';
}
}
/* 實例化一個類 */
console.log(new Animal(),new Animal2());
</script>
</body>
效果
類與繼承
方法一:藉助構造函數來實現繼承
/* 藉助構造函數來實現繼承 */
function fruit(){
this.name = 'fruit';
}
function apple(){
fruit.call(this);
this.type='apple';
}
console.log(new apple);
上述這種方式,是通過改變fruit
構造函數運行時this指向,指向了apple
上,但是fruit
原型鏈上的東西並沒有被繼承。
/* 藉助構造函數來實現繼承 */
function fruit(){
this.name = 'fruit';
}
fruit.prototype.eat = function(){
console.log('吃水果啦!');
}
function apple(){
fruit.call(this);
this.type='apple';
}
console.log(new apple().eat());
因此,通過構造函數來實現的繼承,只能繼承父類構造函數的屬性,如果原型prototype
上面還有方法甚至原型鏈上的方法,不會繼承。
方法二:藉助原型鏈實現繼承
/* 藉助原型鏈實現繼承 */
function fruit(){
this.name = 'fruit';
}
function apple(){
this.type='apple';
}
apple.prototype = new fruit();
console.log(new apple());
掌握之前原型鏈相關的知識,下面的等式應該就比較容易理解了
但這種繼承方式也是有缺點的,下文來探討這個問題:
/* 藉助原型鏈實現繼承 */
function fruit(){
this.name = 'fruit';
this.arr = [1,2,3];
}
function apple(){
this.type='apple';
}
apple.prototype = new fruit();
var app1 = new apple();
var app2 = new apple();
app1.arr.push(4);
console.log(app1,app2);
從上述結果來看,當我們修改某一個對象時,該函數的所有新出的實例對象都會跟着改變,這就造成了污染
問題,肯定不是我們面向對象思想所想要的。(因爲它們引用的是同一個父類實例對象)
方式三:組合方式實現繼承
這種方式就是結合前兩種的優點,彌補它們的缺點。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>面向對象</title>
</head>
<body>
<script>
/* 關於繼承的幾種方式
**使用方法:
**讀者按需將對應模塊註釋取消掉即可
*/
/* 藉助原型鏈實現繼承 */
/*function fruit(){
this.name = 'fruit';
this.arr = [1,2,3];
}
function apple(){
this.type='apple';
}
apple.prototype = new fruit();
var app1 = new apple();
var app2 = new apple();
app1.arr.push(4);
console.log(app1,app2);*/
/* 組合方式實現繼承 */
/**
*此方法的缺點:new fruit() 父類構造函數執行了兩次,可以但沒必要
*/
function fruit(){
this.name = 'fruit';
this.arr = [1,2,3];
}
function apple(){
fruit.call(this);
this.type='apple';
}
apple.prototype = new fruit(); //這裏拿的是父類的實例,沒有自己的constructor
var app1 = new apple();
var app2 = new apple();
app1.arr.push(4);
//console.log(app1,app2);
//console.log(app1.constructor,app2.constructor)
/* 組合方式實現繼承優化1 */
function fruit1(){
this.name = 'fruit';
this.arr = [1,2,3];
}
function apple1(){
fruit.call(this);
this.type='apple';
}
apple1.prototype = fruit1.prototype; //這裏拿的是父類的原型對象,但依舊沒有自己的constructor
var app3 = new apple1();
var app4 = new apple1();
app3.arr.push(4);
//console.log(app3,app4);
//判斷實例
//console.log(app3 instanceof apple1);
//console.log(app3 instanceof fruit1); //這裏無法判斷當前對象是由父類產生的實例對象還是由子類產生的實例對象
//判斷構造函數
//console.log(app3.constructor);
//console.log(app4.constructor); //因爲和父類的原型對象是一個對象,導致constructor也是指向的父類的constructor,無法判斷自己
/* 組合方式實現繼承優化2 */
function fruit2(){
this.name = 'fruit';
this.arr = [1,2,3];
}
function apple2(){
fruit.call(this);
this.type='apple';
}
apple2.prototype = Object.create(fruit2.prototype); //這裏使用Object.create()方法,和之前直接用fruit2.prototype來說,它創建了一箇中間對象,和父類不是指向同一個區域了
//這樣就能區分父類和子類的原型對象了,達到父類和子類原型對象的隔離效果
apple2.prototype.constructor = apple2; //由於隔離了父類子類的原型對象,我們就可以指定子類自己的constructor
var app5 = new apple2();
var app6 = new apple2();
app5.arr.push(4);
console.log(app5,app6);
//判斷實例
console.log(app5 instanceof apple2);
console.log(app5 instanceof fruit2); //因此,這裏可以判斷當前對象是由父類產生的實例對象還是由子類產生的實例對象
//判斷構造函數
console.log(app5.constructor); //指向的是自己的constructor
</script>
</body>
</html>
通信類
題目
- 什麼是同源策略及限制
- 前後端如何通信
- 如何創建Ajax
- 跨域通信的幾種方式(重點)
什麼是同源策略及限制
同源策略限制從一個源加載的文檔或腳本如何與來自另一個源的資源進行交互。
這是一個用於隔離潛在惡意文件的關鍵的安全機制。
源包括協議、域名、端口
- Cookie、LocalStorage和IndexDB無法讀取
- DOM無法獲得
- AJAX請求不能發送
前後端如何通信
- Ajax(同源下的通信)
- WebSocket(不限制,不受同源策略的限制)
- CORS(支持同源通信,也支持跨域通信,新型)
如何創建Ajax
- XMLHttpRequest(高級瀏覽器才支持)對象的工作流程
- 兼容性處理
- 事件的觸發條件
- 事件的觸發順序
跨域通信的幾種方式(重點)
- JSONP
- Hash(改變頁面不刷新,search改變會刷新,因此search不可以)
- postMessage(H5中出現的標準,實現跨域通信)
- WebSocket
- CORS(可以理解爲支持跨域通信的Ajax,在請求頭上加了Origin)
JSONP實現原理:
根據script標籤異步加載而來
將html
加入script
標籤,即把請求發送出去
很關鍵一點是會向服務端發送一個callbackName
,然後服務器就會響應如下內容(下面那個script裏的內容)利用callbackName
作爲函數名來返回,而且本地必須有這個函數名的函數。
Hash與postMessage實現原理
WebSocket實現原理
CORS實現原理
PS:CORS爲什麼支持跨域通信?
瀏覽器回攔截Ajax
請求,如果覺得是跨域的,就會在請求頭上加上origin
。
安全類
題目
-
CSRF
基本概念和縮寫
攻擊原理
防禦措施 -
XSS
CSRF
基本概念和縮寫
CSRF,通常稱爲跨站請求僞造,英文名(Cross-site request forgery)縮寫CSRF
CSRF攻擊原理
- 用戶必須在網站登錄過
- 網站中某個接口存在漏洞
CSRF防禦措施
- Token驗證
- Referer驗證(頁面來源驗證)
- 隱藏令牌(類似Token,隱藏在http的head頭中,不放在鏈接上)
XSS
基本概念和縮寫
跨域腳本攻擊(cross-site scripting)
攻擊原理
比如可以在你的提交區裏面寫上script標籤,即用一些渠道向你的頁面注入js腳本
防禦措施
讓插入的js不可執行
CSRF與XSS區別
CSRF是利用本身的漏洞自動執行接口,依賴於用戶登錄網站
XSS是向頁面注入js,js函數體裏面做想做的事
算法類
題目
- 排序
- 堆棧、隊列、鏈表
- 遞歸
- 波蘭式和逆波蘭式
- …
PS:由於文章篇幅所限,並且算法這一塊需要的是自己平時的積累,這裏就不作長文加載了,關於算法這一塊我會在github裏有相應專欄,記錄題庫。因此,在這裏就給大家分享一些比較好的文章提供學習。
排序
推薦:【再也不怕面試官要你手寫排序算法】一文詳細解讀前後端之各種排序算法及知識拓展(附圖示) JS / C / C++
堆棧、隊列、鏈表
遞歸
波蘭式和逆波蘭式
關於算法的心得
首先,對於前端來說,算法要求沒有後端那麼嚴格,考察的一般不會很刁專,一般就是看下你的思考能力。如果一開始就考察算法題,如果你回答不了的話,也很正常,或許這不是一個關於前端的部門…可能招的是算法工程師,算法這一塊問的話,多半是中間時間段。算法這一塊的話,在於平時積累,如果時間充裕的話,可以深入瞭解一點,這也是面試加分點,如果時間緊迫的話,把上文提到的部分專題弄懂已經不錯了。
二面 / 三面
面試技巧
- 知識面要廣
- 理解要深刻
- 內心要誠實
- 態度要謙虛
- 回答要靈活
- 要學會讚美
渲染機制
題目
- 什麼是DOCTYPE及作用
- 瀏覽器渲染過程
- 重排Reflow
- 重繪Repaint
- 佈局Layout
什麼是DOCTYPE及作用
- DTD(document type ,文檔類型定義)是一系列的語法規則,用來定義XML或(X)HTML的文件類型。瀏覽器會使用它來判斷文件類型,決定使用何種協議來解析,以及切換瀏覽器模式
- DOCTYPE是用來聲明文檔類型和DTD規範的,一個主要的用途便是文件的合法性驗證。如果文件代碼不合法,那麼瀏覽器就會出現一些解析錯誤。(簡單來說,就是告訴瀏覽器我用了哪一個DTD)
PS:這裏要記住html5該如何聲明,以及4.0版本有嚴格模式和傳統模式,具體區別如上圖下劃線所示
瀏覽器渲染過程
簡單快速回答:
第一步,HTML經過HTML解析器解析成爲DOM Tree
第二步,CSS通過CSS解析器形成樣式規則
第三步,將兩個DOM結合形成Render Tree,這裏就類似於告訴瀏覽器渲染樹結構基本出來了,此時有一個平行操作,Layout,經過這個,就能知道元素具體應該顯示在屏幕在哪個位置(寬、高、顏色等)
最後一步,瀏覽器通過GUI畫圖,呈現頁面內容,最後Display顯示頁面
下面通過幾個比較好理解的圖形來將抽象具體化:
DOM Tree
CSSOM Tree
Render Tree
Layout
重排Reflow
定義
DOM結構中的各個元素都有自己的盒子(模型),這些都需要瀏覽器根據各種樣式來計算並根據計算結果將元素放到它該出現的位置,這個過程稱之爲reflow
觸發Reflow
- 當你增加、刪除、修改
DOM
結點時,會導致Reflow
或Repaint
- 當你移動
DOM
的位置,或是搞個動畫的時候 - 當你修改
CSS
樣式的時候 - 當你
Resize
窗口的時候(移動端沒有這個問題),或是滾動的時候 - 當你修改網頁的默認字體時候(影響比較大,性能問題)
重繪Repaint
定義
當各種盒子的位置、大小以及其他屬性,例如顏色、字體大小等確定下來後,瀏覽器於是便把這些元素都按照各自的特性繪製了一遍,於是頁面的內容出現了,這個過程稱之爲repaint
。即頁面需要呈現的內容,一起畫到屏幕上。
觸發Repaint
- DOM改動
- CSS改動
(重點)如何儘量減小Repaint?
比如頁面有一個計算器,用戶在輸入框輸入一些計算表達式,最後顯示計算結果,然後把輸入給隱藏掉。這裏就有兩個交互,先是用戶輸入,將輸入隱藏掉,然後將結果顯示出來。這兩個交互呈現內容不一樣,當然就需要Repaint,那怎麼做少畫點東西?
好像是有一個documentFrame這個東西,把n個節點創建成一個片段,向瀏覽器一次添加這個片段。
(這裏我的朋友考察過,遺留一下這個問題,可以幫助我完善這個問題,謝謝!)
js運行機制
關於這一專題,我之前的文章也是寫的挺多的了。
推薦閱讀:【金三銀四】一個問題就知道你會不會JS了 阿里、頭條真題解析
推薦閱讀:【金三銀四】 一文弄懂 js 數據類型、堆棧內存、作用域(鏈)、閉包知識拓展 (一)
下面就例舉幾個經典題,讀者可以好好體會一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js運行機制</title>
</head>
<body>
<script>
console.log(1);
setTimeout(function(){
console.log(3);
},0);
console.log(2);
</script>
</body>
</html>
for(var i=0;i<4;i++){
setTimeout(function(){
console.log(i);
},1000)
}
題目
- 如何理解JS的單線程
- 什麼是任務隊列
- 什麼是Event Loop
以上三個問題的詳細表述:
推薦閱讀:【金三銀四】 一文弄懂 js 數據類型、堆棧內存、作用域(鏈)、閉包知識拓展 (一)
如何理解JS的單線程
學過JS,不對,聽過JS的同學應該都知道,JS是單線程的,而瀏覽器是多線程的,分配的時間內js只能幹一件事情
什麼是任務隊列
分同步任務和異步任務
什麼是Event Loop
爲了解決同步和異步問題,瀏覽器提供了一個事件隊列 Event Queue,根據特徵不同,分爲微任務和宏任務隊列
執行順序是:主線程代碼 > 微任務 > 宏任務
宏任務:
定時器例如setTimeout(異步)、事件綁定
微任務:
await(異步,執行x函數並等待返回結果,有結果再執行下面代碼)
resolve() / reject() 執行的時候把 then / catch 中的代碼執行
promise、async
特殊情況:
new Promise(同步)會立即執行
總結
- 理解Js的單線程的概念
- 理解任務隊列
- 理解 Event Loop
- 理解哪些語句會放入異步任務隊列
- 理解語句放入異步任務隊列的時機
頁面性能
題目
提升頁面性能的方法有哪些?
- 1、資源壓縮合並,減少HTTP請求
- 2、非核心代碼異步加載——異步加載的方式——異步加載的區別
- 3、利用瀏覽器緩存——緩存的分類——緩存的原理
- 4、使用CDN
- 5、預解析DNS
<meta http-equiv="x-dns-prefetch-control" content="on"> //打開a標籤dns預解析
//有些https默認關了dns預解析,使用上述可以打開(加分點)
<link rel="dns-prefetch" href="//host_name_to_prefetch.com">
異步加載
1、異步加載的方式
- 動態腳本加載(用過js添加到document中,比如加入到body或head中)
- defer
- async
2、異步加載的區別
(1)defer
是在HTML解析完之後纔會執行,如果是多個,按照加載的順序依次執行
(2)async
是在加載完之後立即執行,如果是多個,執行順序和加載順序無關
瀏覽器緩存
1、緩存的分類
-
① 強緩存(不用任何請求,拿過來就用,如果兩個都下發,以第二個
Cache
爲準)Expires(過期時間-服務器絕對時間) Expires:Thu,21 Jan 2017 23:39:02 GMT
(會導致客戶端時間和服務器時間之間時間差問題)
Cache-Control(客戶端相對時間,單位秒) Cache-Control:max-age=3600 -
② 協商緩存(瀏覽器發現本地有這個副本,但是不確定用不用它,於是得向服務器問一下,這個副本要不要用)
Last-Modified(拿到某個資源文件時,通過這個字段服務器下發一個時間) If-Modified-Since (當下次請求這個資源是否發生變化時,是用這個
key
值,對比兩個時間)Last-Modified: Web,26 Jan 2017 00:35:11 GMT
(上述方式會存在問題,例如我可能時間上修改了,但是內容並沒有修改)
Etage(解決上述問題,服務器給Etage值,當過了強緩存時間,瀏覽器請求是否可用副本時,會在http請求頭中用 If-None-Match 當做key值,加上
value
,此value就是Etage的值)
PS:(面試真題-鵝廠)你知道瀏覽器與緩存相關的http頭有哪些?
答案就是上述加粗字體
錯誤監控
問法:如何檢測JS錯誤,如何保證你的產品質量?
題目
- 前端錯誤的分類
- 錯誤的捕獲方式
- 上報錯誤的基本原理
前端錯誤的分類
即時運行錯誤:代碼錯誤
資源加載錯誤
錯誤的捕獲方式
即時運行錯誤的捕獲方式
(1) try…catch
(2)window.onerror(無法捕獲資源加載錯誤,理由如下)
資源加載錯誤(上述原因:因爲資源加載錯誤不會冒泡)
(1)object.onerror
(節點上綁定onerror
事件)
(2)performance.getEntries()
(獲得目前已加載的資源,例如圖片,然後用document.getElementsByTagName(‘img’)來獲取需要加載的圖片,然後用總的去減已加載的,就能知道未加載的有多少了)
(3)Error
事件捕獲(之前說不能冒泡,但可以捕獲)
延伸:跨域的js運行錯誤可以捕獲嗎,錯誤提示什麼,應該怎麼處理?
處理
- 在script標籤增加
crossorigin
屬性 - 設置js資源響應頭 `Access-Control-Allow-Origin:*(可以指定域名)
上報錯誤的基本原理
1、採用Ajax通信的方式上報
2、利用Image對象上報(重點,加分點)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>利用Image對象上報</title>
</head>
<body>
<script>
(new Image()).src='http://baidu.com/test?name=123';
</script>
</body>
</html>
此時,我們查看Nerwork
,可以發現,我們的請求已經發出去了(比Ajax簡單,不用借用任何第三方庫)
三面 / 四面
面試技巧
- 準備要充分
- 描述要熟練
- 引導找時機
- 優勢要發揮
- 回答要靈活
結尾
如若本文有瑕疵需修改的地方,請提出來,謝謝您的貢獻!
歡迎關注微信公衆號:小獅子前端Vue
謝謝您的支持!✿✿ヽ(°▽°)ノ✿
學如逆水行舟,不進則退