混子前端分享一些面試常問乾貨,同時也幫助你們複習和鞏固一波基礎
ps:文章所有由我的總結,知識點分析不全面請自行查漏補缺javascript
假設高度已知,寫出三欄佈局,其中左欄/右欄寬度各爲300px;中間自適應。css
(ps:此題做爲一個小白也要至少答出3種方法,如下分享連混子前端都知道的5種方法)html
HTML部分:
<section class="layout float">
<article class='left-right-center'>
<div class="left"></div>
<div class="right"></div>
<div class="center"></div>
</article>
</section>
CSS部分:
.layout article div{
height: 100px;
}
.layout.float .left{
float: left;
width: 300px;
background: red;
}
.layout.float .right{
float: right;
width: 300px;
background: blue;
}
.layout.float .center{
background: yellow;
}
複製代碼
HTML部分:
<section class="layout absolute">
<article class='left-right-center'>
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</article>
</section>
CSS部分:.layout article div{
height: 100px;
}
.layout.absolute .left,.layout.absolute .right,.layout.absolute .center{
position: absolute;
}
.layout.absolute .left{
left: 0px;
width: 300px;
background: red;
}
.layout.absolute .right{
right: 0px;
width: 300px;
background: blue;
}
.layout.absolute .center{
left: 300px;
right: 300px;
background: yellow;
}
複製代碼
HTML部分:
<section class="layout flexbox">
<article class='left-right-center'>
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</article>
</section>
CSS部分:
.layout article div{
height: 100px;
}
.layout.flexbox .left-right-center{
display: flex;
}
.layout.flexbox .left{
width: 300px;
background: red;
}
.layout.flexbox .center{
flex: 1;
background: yellow;
}
.layout.flexbox .right{
width: 300px;
background: blue;
}
複製代碼
HTML部分:
<section class="layout table">
<article class='left-right-center'>
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</article>
</section>
CSS部分:
.layout article div{
height: 100px;
}
.layout.table .left-right-center{
width: 100%;
display: table;
height: 100px;
}
.layout.table .left-right-center>div{
display: table-cell;
}
.layout.table .left{
width: 300px;
background: red;
}
.layout.table .center{
background: yellow;
}
.layout.table .right{
width: 300px;
background: blue;
}
複製代碼
HTML部分:
<section class="layout grid">
<article class='left-right-center'>
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</article>
</section>
CSS部分:
.layout article div{
height: 100px;
}
.layout.grid .left-right-center{
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;
}複製代碼
補充:未知高度時,彈性盒flex / 表格table很適用,不修改代碼前端
思考:上下高度固定,中間自適應(ps:混子前端都會的,你也必須會!)html5
你必須知道的盒子模型:
java
標準模型:不包含padding和border值,content即盒子width / heightweb
IE盒模型:盒子width / height包含padding和border值面試
box-sizing: content-box; // 標準盒模型(默認)
box-sizing: border-box; // IE盒模型複製代碼
一、dom.style.width/height; // 獲取內聯樣式寬/高[侷限性]
二、dom.currentStyle.width/height; // 獲取是渲染後的寬/高 [只有ie支持]三、window.getComputedStyle(dom).width/height; // 支持chrome、firefox
四、dom.getBoundingClientRect().width/height[left/right/top/bottom]; // 不多人知道,獲取渲染後width/height,計算一個元素絕對位置,根據視窗(viewport),經常使用獲取left/right/top/bottom複製代碼
常見問題:子元素高度100px,margin-top: 10px,此時父元素高度 ?ajax
解:父元素是100px;若是父元素設置overflow: hidden,就是110px;算法
[就是給父元素建立BFC(塊級格式化)]
基本概念:塊級格式化上下文
原理(BFC渲染規則):
怎樣建立BFC,除了給父元素添加overflow: hidden建立BFC,還有那些?
你必須知道幾個關於DOM的知識點
一代:DOM 0級
element.onClick = function(){
// TODO
}複製代碼
爲何從DOM 0級直接到DOM 2級了?DOM 1級標準沒有設定與事件相關的東西
二代:DOM 2級
element.addEventListener('click', function(){
// TODO
}, false);複製代碼
三代:DOM 3級
新增了鼠標,鍵盤等事件
element.addEventListener('keyup', function(){
// TODO
}, false);複製代碼
混子前端認爲分爲三個階段:
捕獲:window > document > HTML > body > HTML結構 > 一層層傳遞到目標元素
冒泡:捕獲反過來就是冒泡,從目標元素傳遞到window
如:ul > li 點擊觸發,給ul綁定onclick方法,此時:
target:<li>
currentTarget:<ul>
var eve = new Event('custome'); // 聲明自定義事件
ev.addEventListener('custome', function(){
console.log('custome');
});
ev.dispatchEvent(eve); // dispatchEvent api觸發複製代碼
補充:網站如今記住的是身份,不是http協議作到的,而是經過服務端加session作到的
客戶端輸入url,服務端響應;
報文分爲2部分,即:請求報文 響應報文,如圖所示:
GET:獲取資源
POST:傳輸資源
PUT:更新資源
DELETE:刪除資源
HEAD:得到報文首部
若是你對本身有追求,那如下你也要知道:
200:客戶端請求成功
206:客戶發送了一個帶有Range頭的GET請求,服務器完成;如:客戶端發起0-10000字節請求,服務器返回206,服務端會根據Range頭部截一部分,響應回客戶端(客戶端要求的Range範圍)
301:所請求頁面已經轉移至新的url(永久重定向)
302:所請求頁面已經臨時轉移至新的url(臨時重定向)
304:客戶端口有緩衝的文檔併發出了一個條件性的請求,服務器告訴客戶端,原來緩衝的文檔還能夠繼續使用 [ 服務器告訴客戶端有緩存,能夠取緩存用,不用在服務器取 ]
400:客戶端有語法錯誤,不能被服務器所理解
401:請求未經受權
403:對被請求頁面訪問禁止
404:資源不存在
500:服務器錯誤
503:服務器臨時過載或宕機
HTTP協議採用「請求 -- 應答」模式,當使用普通模式,即非keep-alive(持久鏈接)時,每一個請求/應答客戶端和服務器都要新建一個鏈接,完成以後當即斷開鏈接(HTTP無鏈接協議)
當使用keep-alive模式(持久鏈接)時,keep-alive功能使客戶端到服務端的鏈接持久有效,當出現對服務器的後續請求時,keep-alive功能避免了創建或者從新創建鏈接
注意:持久鏈接1.1版本才支持,1.0版本不支持
當使用持久鏈接的狀況下,某個鏈接上消息的傳遞相似於:
請求1 > 響應1 > 請求2 > 響應2 > 請求3 > 響應3
某個鏈接上的消息變成了相似如下這樣(管線化):
[請求1 > 請求2 > 請求3 ] > [響應1 > 響應2 > 響應3]
注意:
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)複製代碼
Object.create()建立對象是用原型鏈鏈接的;o3的__proto__指向P對象,下文會說o3.__proto__指向構造函數的原型對象,也就是說原型就是P
o3.__proto__ === P; // true複製代碼
ps:Object.create()方法是把參數中對象做爲一個新對象原型對象賦給o3的,o3自己不具有name屬性,是經過原型鏈鏈接它的原型對象;
ps:經過prototype 和 __proto__完成原型鏈向上找的過程,Object.prototype是整個原型鏈的頂端,到這裏未知
問題來了:原型對象和原型鏈到底起什麼做用?
解答:構造函數中增長不少屬性和方法,實例就能夠共用,當有不少個實例想去公用方法時,不可能每一個都拷貝一份,如今考慮應該有個東西存,這個東西就是原型對象
注意:
ps:主要在這條原型鏈上的構造函數都是實例對象構造函數
instanceof原理是 實例對象__proto__屬性 和 構造函數 prototype判斷是否是同一個引用,返回true / false
JS code:
function M (){ this.name = name };
var o = new M()
o instanceof M; // true
o instanceof Object; // true複製代碼
注意爲何 o instanceof Object 也返回true ?
JS code:
o.__proto__ === M.prototype; // true
M.prototype.__proto__ === Object.prototype; // true複製代碼
JS code:
o.__proto__.constructor === M; // true
o.__proto__.constructor === Object; // false複製代碼
因此說使用constructor判斷比instanceof更嚴謹
JS code:
var newF = function(func){
var o = Object.create(func.prototype); // 1.建立對象關聯構造函數原型對象
var k = func.call(o); // 2.執行構造函數
if(typeof k === 'object'){ // 3.判斷構造函數運行結果,是否爲對象類型
return k;
}else{
return o;
}
}複製代碼
源:協議 / 域名 / 端口 80(默認),這三個有一項不一樣就跨域了
限制:不是同一個源文檔沒有權利修改另外一個源文檔
var xhr = XMLHttpRequest ? new XMLHttpRequest() : new Window.ActiveXObject("Microsoft.XMLHTTP"); // 兼容寫法
xhr.setRequestHeader(); // header頭部信息
xhr.open("GET","/try/ajax/ajax_info.txt", true);
xhr.send(); // 發送
// xhr.onload判斷xhr.status = 200 || 206 || 304 複製代碼
Ajax是不能發送跨域通訊的,瀏覽器在識別用Ajax發送一個跨域請求時,它會在http頭部加origin來容許跨域通訊,若是不加就被攔截,這也是前端混子所理解CORS原理
JSONP
原理:在出現postMessage和CORS前,用script標籤的異步加載實現;
JS code:
// 發送
<script src="http://www.abc.com/?data=name&callback=jsonp"></script>
// 返回
<script>
jsonp({
data:{}
}) </script>
// 發送
document.getElementByTagName('head')[0].appendChild('script');複製代碼
實現:
1.告訴服務端callback名稱,未來是做爲函數名返回的
2.本地必須有jsonp全局函數,後面才能把數據執行出來
Hash
應用場景:頁面A經過iframe潛入跨域頁面B併發送消息
var B = document.getElementByTagName('iframe');
B.src = B.src + '#' + 'data';
window.onhashchange = function(){ // 寫在B頁面中, 監聽hash有沒有改變
var data = window.location.hash;
}複製代碼
postMessage
應用場景同上
// A頁面發送到B
B.window.postMessage('data', 'http://B.com');
// B頁面接收A
window.addEventListener('message',function(event){
console.log(event.origin); // 拿到A的源
console.log(event.source); // Awindow的對象
console.log(event.data); // 發送的消息拿到了
}, false);複製代碼
Websocket
var ws = new Websocket('wss: echo.websocket.org'); // 指向服務器地址, ws不加密, wss加密
ws.onopen = function(){ ws.send(); }; // 發送出去
ws.onmessage = function(ev){
ev.data;
ws.close; // close斷開
}複製代碼
CORS
新型的Ajax通訊api:fetch 實現CORS通訊
fetch('/some/url',{
method: 'get'
}).then(function(response){
}).catch(function(error){
});複製代碼
CSRF:稱爲跨站請求僞造
ps:引誘點擊後訪問網站A後,瀏覽器自動上傳cookie,A網站對身份從新確認(合法),就執行了動做,完成CSRF攻擊
實現CSRF不可缺乏的條件:
CSRF防護措施:
XSS稱爲跨域腳本攻擊
攻擊原理:不須要作登錄驗證,核心原理是向頁面注入腳本 [ 評論區是最好最入css攻擊的,在提交區裏面寫script標籤,img標籤等 ],xss是利用合法渠道注入JS
防護措施:宗旨是不讓頁面執行插入的JS腳本
XSS與CSRF對比區別
你要知道的:DTD(document type definition)告訴瀏覽器我是什麼類型,瀏覽器根據類型來判斷用什麼引擎優化它;如:XML / HTML
這裏是做用:DOCTYPE是聲明文檔類型和DTD規範的,直接告訴瀏覽器當前文檔包含哪些DTD(文檔類型)
<!DOCTYPE HTML> // html5
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//en" "http://www.w3. org/TR/html4/strict.dtd"> // HTML4嚴格:不包含展現性和棄用元素(front)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//en" "http://www.w3. org/TR/html4/loose.dtd"> // HTML4傳統:包含展現性和棄用元素(front)
複製代碼
瀏覽器根據各類樣式計算放在它該出現的問題,如:JS修改div中內容(即觸發Reflow)
常見觸發Reflow
屏幕上頁面的呈現內容
常見觸發Repaint
JS是單線程的(同一事件只能作一件事);這裏混子前端拿道面爛了的面試題來舉例:
JS代碼:
for (var i = 1;i <= 5;i ++) {
setTimeout(function timer() {
console.log(i)
},i * 1000)
}複製代碼
對JS做用域、閉包以及事件循環等概念不瞭解的夥伴會想固然的回答:
第一次循環,隔一秒輸出1;
第二次循環,隔一秒輸出2;
第三次循環,隔一秒輸出3;
第四次循環,隔一秒輸出4;
第五次循環,隔一秒輸出5;
或者還有夥伴預期結果是分別輸出數字1~5,每秒依次,每次一個。
但實際結果你們粘貼到控制檯就都知道,以一秒的頻率輸出五個6。
下面來過一下上面提到的知識點:
做用域:這裏我引用《你不知道的javascript》中的一個比喻,能夠把做用域鏈想象成一座高樓,第一層表明當前執行做用域,樓的頂層表明全局做用域。咱們在查找變量時會先在當前樓層進行查找,若是沒有找到,就會坐電梯前往上一層樓,若是仍是沒有找到就繼續向上找,以此類推。到達頂層後(全局做用域),可能找到了你所需的變量,也可能沒找到,但不管如何查找過程都將中止。
閉包:個人理解是在傳遞函數類型的變量時,該函數會保留定義它的所在函數的做用域。讀起來可能比較繞,或者能夠簡單的這麼理解,A函數中定義了B函數而且它返回了B函數,那麼無論B函數在哪裏被調用或如何被調用,它都會保留A函數的做用域。
事件循環:這個概念深刻起來很複雜,下面新開一個段落詳談:
提及事件循環,不得不提起任務隊列。事件循環只有一個,但任務隊列可能有多個,任務隊列可分爲宏任務(macro-task)和微任務(micro-task)。
XHR回調、事件回調(鼠標鍵盤事件)、setImmediate、setTimeout、setInterval、indexedDB數據庫操做等I/O以及UI rendering都屬於宏任務(也有文章說UI render不屬於宏任務,目前尚未定論)
process.nextTick、Promise.then、Object.observer(已經被廢棄)、MutationObserver(html5新特性)屬於微任務。注意進入到任務隊列的是具體的執行任務的函數。
好比上述例子setTimeout()中的timer函數。另外不一樣類型的任務會分別進入到他們所屬類型的任務隊列,好比全部setTimeout()的回調都會進入到setTimeout任務隊列,全部then()回調都會進入到then隊列。當前的總體代碼咱們能夠認爲是宏任務。事件循環從當前總體代碼開始第一次事件循環,而後再執行隊列中全部的微任務,當微任務執行完畢以後,事件循環再找到其中一個宏任務隊列並執行其中的全部任務,而後再找到一個微任務隊列並執行裏面的全部任務,就這樣一直循環下去。這就是我所理解的事件循環。
繼續看個栗子:
JS代碼:
console.log('global')
setTimeout(function () {
console.log('timeout1')
new Promise(function (resolve) {
console.log('timeout1_promise')
resolve()
}).then(function () {
console.log('timeout1_then')
})
},2000)
for (var i = 1;i <= 5;i ++) {
setTimeout(function() {
console.log(i)
},i*1000)
console.log(i)
}
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('then1')
})
setTimeout(function () {
console.log('timeout2')
new Promise(function (resolve) {
console.log('timeout2_promise')
resolve()
}).then(function () {
console.log('timeout2_then')
})
}, 1000)
new Promise(function (resolve) {
console.log('promise2')
resolve()
}).then(function () {
console.log('then2')
})
複製代碼
來一步一步分析以上代碼:
再回過頭來看上面那個問題,理解了事件循環的機制,問題就很簡單了。for循環時setTimeout()不是當即執行的,它們的回調被push到了宏任務隊列當中,而在執行任務隊列裏的回調函數時,變量i早已變成了6。那如何獲得想要的結果呢?很簡單,原理就是須要給循環中的setTimeout()建立一個閉包做用域,讓它執行的時候找到的變量i是正確的。
混子前端給出以下5種解決方案:
JS代碼
for(var i = 0;i < 5; i++){
(function(i){
setTimeout(function timer(){
console.log(i);
}, i * 1000)
})(i);
}
複製代碼
JS代碼
for(let i = 0;i<5;i++) {
setTimeout(function timer(){
console.log(i);
}, i * 1000);
}
複製代碼
利用ES 5引入的bind函數
JS代碼
for (var i=1; i<=5; i++) {
setTimeout( function timer(i) {
console.log(i);
}.bind(null,i), i*1000 );
}
複製代碼
利用setTimeout第三個參數
JS代碼
for (var i=1; i<=5; i++) {
setTimeout(function timer(i) {
console.log(i);
}, i*1000,i );
}
複製代碼
把setTimeout用一個方法單獨出來造成閉包
JS代碼
var loop = function (i) {
setTimeout(function timer() {
console.log(i);
}, i*1000);
};
for (var i = 1;i <= 5; i++) {
loop(i);
}複製代碼
<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="//host_name_to_prefetch.com">複製代碼
首先咱們要知道錯誤分類:
(一)若是是即時性錯誤
(二)若是是資源加載性錯誤
JS代碼
window.addEventListener('error', function(){
// ****
}, true);複製代碼
ps:若是JS錯誤是跨域的,能夠在script標籤添加crossorigin屬性,同時在響應JS資源時,設置JS資源頭Access-Control-Allow-Origin就能夠拿到錯誤信息了
這裏上報錯誤的原理:利用ajax通信上報 / 也能夠利用image對象上報
JS代碼
(new Image()).src = "http://baidu.com/tesjk?r=tksjk";複製代碼
利用這種方式比ajax簡單,也能實現資源上報
因爲本人也是混子前端,不一一列舉,但做爲一名合格的前端,算法是必不可少的。
ps:請隨意吐槽本混子,會虛心接受
好了,混子前端就總結到這裏,還請留意混子前端不定時的更新....