前端面試題

說一下瀏覽器緩存:javascript

緩存分爲兩種:強緩存和協商緩存,根據響應的header內容來決定。

強緩存相關字段有expires,cache-control。若是cache-control與expires同時存在的話,cache-control的優先級高於expires。html

協商緩存相關字段有Last-Modified/If-Modified-Since,Etag/If-None-Matchjava

fetch發送2次請求的緣由:mysql

fetch發送post請求的時候,老是發送2次,第一次狀態碼是204,第二次才成功?
緣由很簡單,由於你用fetch的post請求的時候,致使fetch 第一次發送了一個Options請求,詢問服務器是否支持修改的請求頭,若是服務器支持,則在第二次中發送真正的請求。react

第一次是探域,至於跨域的狀況下才會發送兩次git

 

在地址欄裏輸入一個URL,到這個頁面呈現出來,中間會發生什麼?es6

這是一個必考的面試問題,
輸入url後,首先須要找到這個url域名的服務器ip,爲了尋找這個ip,瀏覽器首先會尋找緩存,查看緩存中是否有記錄,緩存的查找記錄爲:瀏覽器緩存-》系統緩存-》路由器緩存,緩存中沒有則查找系統的hosts文件中是否有記錄,若是沒有則查詢DNS服務器,獲得服務器的ip地址後,瀏覽器根據這個ip以及相應的端口號,構造一個http請求,這個請求報文會包括此次請求的信息,主要是請求方法,請求說明和請求附帶的數據,並將這個http請求封裝在一個tcp包中,這個tcp包會依次通過傳輸層,網絡層,數據鏈路層,物理層到達服務器,服務器解析這個請求來做出響應,返回相應的html給瀏覽器,由於html是一個樹形結構,瀏覽器根據這個html來構建DOM樹,在dom樹的構建過程當中若是遇到JS腳本和外部JS鏈接,則會中止構建DOM樹來執行和下載相應的代碼,這會形成阻塞,這就是爲何推薦JS代碼應該放在html代碼的後面,以後根據外部央視,內部央視,內聯樣式構建一個CSS對象模型樹CSSOM樹,構建完成後和DOM樹合併爲渲染樹,這裏主要作的是排除非視覺節點,好比script,meta標籤和排除display爲none的節點,以後進行佈局,佈局主要是肯定各個元素的位置和尺寸,以後是渲染頁面,由於html文件中會含有圖片,視頻,音頻等資源,在解析DOM的過程當中,遇到這些都會進行並行下載,瀏覽器對每一個域的並行下載數量有必定的限制,通常是4-6個,固然在這些全部的請求中咱們還須要關注的就是緩存,緩存通常經過Cache-Control、Last-Modify、Expires等首部字段控制。 Cache-Control和Expires的區別在於Cache-Control使用相對時間,Expires使用的是基於服務器 端的絕對時間,由於存在時差問題,通常採用Cache-Control,在請求這些有設置了緩存的數據時,會先 查看是否過時,若是沒有過時則直接使用本地緩存,過時則請求並在服務器校驗文件是否修改,若是上一次 響應設置了ETag值會在此次請求的時候做爲If-None-Match的值交給服務器校驗,若是一致,繼續校驗 Last-Modified,沒有設置ETag則直接驗證Last-Modified,再決定是否返回304
 
簡單點說:
 
DNS解析

TCP鏈接web

發送HTTP請求面試

服務器處理請求並返回HTTP報文redis

瀏覽器解析渲染頁面

鏈接結束

 
瀏覽器在生成頁面的時候,會生成那兩顆樹?
 
構造兩棵樹,DOM樹和CSSOM規則樹

當瀏覽器接收到服務器相應來的HTML文檔後,會遍歷文檔節點,生成DOM樹,

CSSOM規則樹由瀏覽器解析CSS文件生成,

 

csrf和xss的網絡攻擊及防範

CSRF:跨站請求僞造,能夠理解爲攻擊者盜用了用戶的身份,以用戶的名義發送了惡意請求,好比用戶登陸了一個網站後,馬上在另外一個tab頁面訪問量攻擊者用來製造攻擊的網站,這個網站要求訪問剛剛登錄的網站,併發送了一個惡意請求,這時候CSRF就產生了,好比這個製造攻擊的網站使用一張圖片,可是這種圖片的連接倒是能夠修改數據庫的,這時候攻擊者就能夠以用戶的名義操做這個數據庫,防護方式的話:使用驗證碼,檢查https頭部的refer,使用token

XSS:跨站腳本攻擊,是說攻擊者經過注入惡意的腳本,在用戶瀏覽網頁的時候進行攻擊,好比獲取cookie,或者其餘用戶身份信息,能夠分爲存儲型和反射型,存儲型是攻擊者輸入一些數據而且存儲到了數據庫中,其餘瀏覽者看到的時候進行攻擊,反射型的話不存儲在數據庫中,每每表現爲將攻擊代碼放在url地址的請求參數中,防護的話爲cookie設置httpOnly屬性,對用戶的輸入進行檢查,進行特殊字符過濾

 

描述一下XSS和CRSF攻擊?防護方法?

 

XSS, 即爲(Cross Site Scripting), 中文名爲跨站腳本, 是發生在目標用戶的瀏覽器層面上的,當渲染DOM樹的過程成發生了不在預期內執行的JS代碼時,就發生了XSS攻擊。大多數XSS攻擊的主要方式是嵌入一段遠程或者第三方域上的JS代碼。其實是在目標網站的做用域下執行了這段js代碼。

CSRF(Cross Site Request Forgery,跨站請求僞造),字面理解意思就是在別的站點僞造了一個請求。專業術語來講就是在受害者訪問一個網站時,其 Cookie 尚未過時的狀況下,攻擊者僞造一個連接地址發送受害者並欺騙讓其點擊,從而造成 CSRF 攻擊。

XSS防護的整體思路是:對輸入(和URL參數)進行過濾,對輸出進行編碼。也就是對提交的全部內容進行過濾,對url中的參數進行過濾,過濾掉會致使腳本執行的相關內容;而後對動態輸出到頁面的內容進行html編碼,使腳本沒法在瀏覽器中執行。雖然對輸入過濾能夠被繞過,可是也仍是會攔截很大一部分的XSS攻擊。

防護CSRF 攻擊主要有三種策略:驗證 HTTP Referer 字段;在請求地址中添加 token 並驗證;在 HTTP 頭中自定義屬性並驗證。

說一下對Cookie和Session的認知,Cookie有哪些限制?

 

1.    cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。

 

2.    cookie不是很安全,別人能夠分析存放在本地的COOKIE並進行COOKIE欺騙
考慮到安全應當使用session。

 

3.    session會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能
考慮到減輕服務器性能方面,應當使用COOKIE。

 

4.    單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個cookie。

什麼是BFC?什麼是IFC?

不要試圖去講解 BFC 的定義!!
如何說明 BFC ,舉例子!!不要試圖去講定義!!

格式化上下文(block formatting context) 

當一個HTML元素知足下面條件的任何一點,均可以產生Block Formatting Context:
a、float的值不爲none
b、overflow的值不爲visible
c、display的值爲table-cell, table-caption, inline-block中的任何一個
d、position的值不爲relative和static

 IFC(Inline Formatting Context)即行內格式化上下文。常規流(也稱標準流、普通流)是一個文檔在被顯示時最多見的佈局形態。

(塊級格式化上下文,用於清楚浮動,防止margin重疊等)

直譯成:塊級格式化上下文,是一個獨立的渲染區域,而且有必定的佈局規則。

BFC區域不會與float box重疊

BFC是頁面上的一個獨立容器,子元素不會影響到外面

計算BFC的高度時,浮動元素也會參與計算

那些元素會生成BFC:

根元素

float不爲none的元素

position爲fixed和absolute的元素

display爲inline-block、table-cell、table-caption,flex,inline-flex的元素

overflow不爲visible的元素

 

BFC 特性(功能)

  1. 使 BFC 內部浮動元素不會處處亂跑;
  2. 和浮動元素產生邊界。

 

畫一條0.5px的線

採用meta viewport的方式

<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />

採用border-image的方式

採用transform: scale()的方式

.hairline-bottom {
  position: relative;
  border: none;
}
.hairline-bottom::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  border-bottom: 1px solid #dddee3;
  width: 100%;
  -webkit-transform: scale(1, 0.5);
  transform: scale(1, 0.5);
  -webkit-transform-origin: center bottom;
  transform-origin: center bottom;
  z-index: 1;
}

介紹一下盒模型

 

CSS盒模型本質上是一個盒子,封裝周圍的HTML元素,它包括:邊距,邊框,填充,和實際內容。

標準盒模型:一個塊的總寬度=width+margin(左右)+padding(左右)+border(左右)

怪異盒模型:一個塊的總寬度=width+margin(左右)(既width已經包含了padding和border值)

設置盒模型:box-sizing:border-box

 

對象深度克隆的簡單實現

function deepClone(obj){
var newObj= obj instanceof Array ? []:{};
for(var item in obj){
var temple= typeof obj[item] == 'object' ? deepClone(obj[item]):obj[item];
newObj[item] = temple;
}
return newObj;
}
ES5的經常使用的對象克隆的一種方式。注意數組是對象,可是跟對象又有必定區別,因此咱們一開始判斷了一些類型,決定newObj是對象仍是數組~

 

 null == undefined爲何

要比較相等性以前,不能將null 和 undefined 轉換成其餘任何值,但 null == undefined 會返回 true 。ECMAScript規範中是這樣定義的。

 

簡單介紹一下symbol

Symbol是ES6 的新增屬性,表明用給定名稱做爲惟一標識,這種類型的值能夠這樣建立,let id=symbol(「id」)

Symbl確保惟一,即便採用相同的名稱,也會產生不一樣的值,咱們建立一個字段,僅爲知道對應symbol的人能訪問,使用symbol頗有用,symbol並非100%隱藏,有內置方法Object.getOwnPropertySymbols(obj)能夠得到全部的symbol。 
也有一個方法Reflect.ownKeys(obj)返回對象全部的鍵,包括symbol。

因此並非真正隱藏。但大多數庫內置方法和語法結構遵循通用約定他們是隱藏的

 

NaN

NaN是JS中的特殊值,表示非數字,NaN不是數字,可是他的數據類型是數字,它不等於任何值,包括自身,在布爾運算時被當作false,NaN與任何數運算獲得的結果都是NaN,

 

redux裏經常使用方法

提供  getState() 方法獲取 state;

提供 dispatch(action) 方法更新 state;

經過 subscribe(listener) 註冊監聽器;

 

react的生命週期函數

初始化
1、getDefaultProps()

設置默認的props,也能夠用dufaultProps設置組件的默認屬性.

2、getInitialState()

在使用es6的class語法時是沒有這個鉤子函數的,能夠直接在constructor中定義this.state。此時能夠訪問this.props

3、componentWillMount()

組件初始化時只調用,之後組件更新不調用,整個生命週期只調用一次,此時能夠修改state。

4、 render()

react最重要的步驟,建立虛擬dom,進行diff算法,更新dom樹都在此進行。此時就不能更改state了。

5、componentDidMount()

組件渲染以後調用,只調用一次。

更新

6、componentWillReceiveProps(nextProps)

組件初始化時不調用,組件接受新的props時調用。

7、shouldComponentUpdate(nextProps, nextState)

react性能優化很是重要的一環。組件接受新的state或者props時調用,咱們能夠設置在此對比先後兩個props和state是否相同,若是相同則返回false阻止更新,由於相同的屬性狀態必定會生成相同的dom樹,這樣就不須要創造新的dom樹和舊的dom樹進行diff算法對比,節省大量性能,尤爲是在dom結構複雜的時候

8、componentWillUpdata(nextProps, nextState)

組件初始化時不調用,只有在組件將要更新時才調用,此時能夠修改state

9、render()

組件渲染

10、componentDidUpdate()

組件初始化時不調用,組件更新完成後調用,此時能夠獲取dom節點。

卸載

11、componentWillUnmount()

組件將要卸載時調用,一些事件監聽和定時器須要在此時清除。
View Code

 

setState以後的流程

在代碼中調用setState函數以後,React 會將傳入的參數對象與組件當前的狀態合併,而後觸發所謂的調和過程(Reconciliation)。 通過調和過程,React 會以相對高效的方式根據新的狀態構建 React 元素樹而且着手從新渲染整個UI界面。 在 React 獲得元素樹以後,React 會自動計算出新的樹與老樹的節點差別,而後根據差別對界面進行最小化重渲染。 在差別計算算法中,React 可以相對精確地知道哪些位置發生了改變以及應該如何改變,這就保證了按需更新,而不是所有從新渲染。

 

tcp三次握手過程

 

第一次握手:起初兩端都處於CLOSED關閉狀態,Client將標誌位SYN置爲1,隨機產生一個值seq=x,並將該數據包發送給Server,Client進入SYN-SENT狀態,等待Server確認;

第二次握手:Server收到數據包後由標誌位SYN=1得知Client請求創建鏈接,Server將標誌位SYN和ACK都置爲1,ack=x+1,隨機產生一個值seq=y,並將該數據包發送給Client以確認鏈接請求,Server進入SYN-RCVD狀態,此時操做系統爲該TCP鏈接分配TCP緩存和變量;

第三次握手:Client收到確認後,檢查ack是否爲x+1,ACK是否爲1,若是正確則將標誌位ACK置爲1,ack=y+1,而且此時操做系統爲該TCP鏈接分配TCP緩存和變量,並將該數據包發送給Server,Server檢查ack是否爲y+1,ACK是否爲1,若是正確則鏈接創建成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client和Server就能夠開始傳輸數據。

 

TCP和UDP的區別,爲何三次握手四次揮手

TCP和UDP之間的區別 OSI 和TCP/IP 模型在傳輸層定義兩種傳輸協議:TCP(或傳輸控制協議)和UDP(或用戶數據報協議)。 UDP 與TCP 的主要區別在於UDP 不必定提供可靠的數據傳輸。 事實上,該協議不能保證數據準確無誤地到達目的地。

爲何TCP要進行四次揮手呢?

由於是雙方彼此都創建了鏈接,所以雙方都要釋放本身的鏈接,A向B發出一個釋放鏈接請求,他要釋放連接代表再也不向B發送數據了,此時B收到了A發送的釋放連接請求以後,給A發送一個確認,A不能再向B發送數據了,它處於FIN-WAIT-2的狀態,可是此時B還能夠向A進行數據的傳送。此時B向A 發送一個斷開鏈接的請求,A收到以後給B發送一個確認。此時B關閉鏈接。A也關閉鏈接。


爲何要有TIME-WAIT這個狀態呢,這是由於有可能最後一次確認丟失,若是B此時繼續向A發送一個我要斷開鏈接的請求等待A發送確認,但此時A已經關閉鏈接了,那麼B永遠也關不掉了,因此咱們要有TIME-WAIT這個狀態。

固然TCP也並非100%可靠的。
View Code

Redis和 mysql

(1)類型上
從類型上來講,mysql是關係型數據庫,redis是緩存數據庫

(2)做用上

mysql用於持久化的存儲數據到硬盤,功能強大,可是速度較慢

redis用於存儲使用較爲頻繁的數據到緩存中,讀取速度快

(3)需求上

mysql和redis由於需求的不一樣,通常都是配合使用。
View Code

 

git 怎麼刪除一個遠程/本地分支

刪除遠程分支

git push origin --delete dev

 

刪除本地分支

git branch -d dev

 

查看分支狀況

git branch -a

 

兩個數組比較,判斷是否有相同元素

要判斷JS中的兩個數組是否相同,須要先將數組轉換爲字符串,再做比較。如下兩行代碼將返回true

<script type="text/javascript">
        alert([].toString()== [].toString());
        alert([].toString()===[].toString());
</script>

數組去重通常用什麼方法,數據量大又用什麼方法

/*
* 速度最快, 佔空間最多(空間換時間)
*
* 該方法執行的速度比其餘任何方法都快, 就是佔用的內存大一些。
* 現思路:新建一js對象以及新數組,遍歷傳入數組時,判斷值是否爲js對象的鍵,
* 不是的話給對象新增該鍵並放入新數組。
* 注意點:判斷是否爲js對象鍵時,會自動對傳入的鍵執行「toString()」,
* 不一樣的鍵可能會被誤認爲同樣,例如n[val]-- n[1]、n["1"];
* 解決上述問題仍是得調用「indexOf」。*/
function uniq(array){
    var temp = {}, r = [], len = array.length, val, type;
    for (var i = 0; i < len; i++) {
        val = array[i];
        type = typeof val;
        if (!temp[val]) {
            temp[val] = [type];
            r.push(val);
        } else if (temp[val].indexOf(type) < 0) {
            temp[val].push(type);
            r.push(val);
        }
    }
    return r;
}

var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));
View Code
const removeDuplicateItems = arr => [...new Set(arr)]; console.log(removeDuplicateItems([42, 'foo', 42, 'foo', true, true])); // => [42, "foo", true]
View Code

set和obj

數據量大就用排序方法去重唄 

 

爲何JS中0.1+0.2 != 0.3


因爲0.1轉換成二進制時是無限循環的,因此在計算機中0.1只能存儲成一個近似值。

 

WebView和原生是如何通訊

== 和 ===的區別,什麼狀況下用相等==

兩個對象如何比較

https://www.jianshu.com/p/90ed8b728975

prototype和——proto——區別

JS爲何要區分微任務和宏任務

發佈-訂閱和觀察者模式的區別

for..in 和 object.keys的區別

獲取對象的屬性的方法

關於標題中方法和語句的基本用法能夠參閱以下兩篇文章:

(1).JavaScript Object.keys()一章節。

(2).JavaScript for in 語句一章節。

Object.keys方法對數組進行遍歷操做,能夠看到獲取的是數組的索引。

數組的索引都是數字,可是經過此方法獲取的都會被轉換爲字符串。

for in語句:

此語句能夠遍歷普通對象,也能夠遍歷數組,可是不建議使用它遍歷數組。

三.異同總結以下:

(1).均可以遍歷對象與數組。

(2).獲取的都是對象或者數組的鍵(數組的鍵就是元素索引),獲取的值都會被轉換爲字符串。

(3).獲取鍵的順序二者是徹底相同的。

(4).瀏覽器支持有所差別,Object.keys方法低版本IE瀏覽器不支持。

(5).Object.keys方法不會獲取原型鏈上的鍵,可是for in是能夠的。

文章

react的理念是什麼(拿函數式編程來作頁面渲染)
JS是什麼範式語言(面向對象仍是函數式編程)

輸出下面的執行順序

setTimeout(function(){
        console.log('1')
});
 
new Promise(function(resolve){
    console.log('2');
        resolve();
}).then(function(){
    console.log('3')
});
        console.log('4');

看一下宏任務和微任務

同步和異步任務分別進入不一樣的執行"場所",同步的進入主線程,異步的進入Event Table並註冊函數。當指定的事情完成時,Event Table會將這個函數移入Event Queue。主線程內的任務執行完畢爲空,會去Event Queue讀取對應的函數,進入主線程執行。上述過程會不斷重複,也就是常說的Event Loop(事件循環)。

宏任務和微任務

而宏任務通常是:包括總體代碼script,setTimeout,setInterval。

微任務:Promise,process.nextTick。

記住就好了。

因此正確的執行結果固然是:

2,4,3,1。
View Code

由於settimeout是宏任務,雖然先執行的他,可是他被放到了宏任務的eventqueue裏面,而後代碼繼續往下檢查看有沒有微任務,檢測到Promise的then函數把他放入了微任務序列。等到主線進程的全部代碼執行結束後。先從微任務queue裏拿回掉函數,而後微任務queue空了後再從宏任務的queue拿函數。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息