前端常見面試題
三欄佈局
- float
<div> <section class="a1">a1</section> <section class="a2">a2</section> <section class="a3">a3</section> <section class="a4">a4</section> <section class="a5">a5</section> </div> div { width: 180px; height: 50px; } section { float: left; } .a1 { width: 50px; height: 50px; background-color: tan; } .a2 { float: right; width: 50px; height: 50px; background-color: tan; } .a3 { width: 80px; height: 25px; background-color: red; } .a4 { width: 40px; height: 25px; background-color: #ddd; } .a5 { width: 40px; height: 25px; background-color: #666; } 複製代碼
- position
div { width: 180px; height: 50px; position: relative; } .a1 { position: absolute; width: 50px; height: 50px; background-color: red; } .a2 { position: absolute; left: 50px; width: 80px; height: 25px; background-color: blue; } .a3 { position: absolute; left: 50px; top: 25px; width: 40px; height: 25px; background-color: green; } .a4 { position: absolute; left: 90px; top: 25px; width: 40px; height: 25px; background-color: tan; } .a5 { position: absolute; width: 50px; height: 50px; left: 130px; background-color: red; } 複製代碼
- flex
div {
width: 180px;
height: 50px;
display: flex;
flex-flow: column wrap;
align-content: flex-start;
}
.a1 {
width: 50px;
height: 50px;
background-color: red;
}
.a2 {
width: 80px;
height: 25px;
background-color: tan;
}
.a3 {
flex-grow: 1;
background-color: aqua;
}
.a4 {
width: 25px;
height: 50px;
background-color: #fff;
}
.a5 {
flex-grow: 1;
background-color: red;
}
複製代碼
- 三欄等寬佈局
div {
width: 180px;
height: 50px;
display: flex;
background-color: tan;
}
section {
flex: auto;
}
.a1 {
background-color: #fff;
}
.a2 {
background-color: #444;
}
.a3 {
background-color: red;
}
複製代碼
垂直居中
- position
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
複製代碼
- table
div {
width: 100px;
height: 100px;
position: relative;
background-color: tan;
display: table-cell;
vertical-align: middle;
text-align: center;
}
span {
background-color: red;
}
複製代碼
- 行內塊
div {
width: 100px;
height: 100px;
position: relative;
background-color: tan;
}
section {
width: 50px;
height: 50px;
display: inline-block;
margin: 25px;
background-color: red;
}
複製代碼
- float
div {
width: 100px;
height: 100px;
position: relative;
background-color: tan;
}
section {
width: 50px;
height: 50px;
margin: 25px;
float: left;
background-color: red;
}
複製代碼
- line-height
div {
width: 100px;
height: 100px;
background-color: tan;
text-align: center;
line-height: 100px;
}
span{
background-color: #fff;
vertical-align: middle;
}
複製代碼
盒模型
margin-box, border-box, padding-box, content-box
首先是最內層content-box,用來顯示元素信息
向外是padding-box,主要用於設置元素四個方向的內邊距,
再向外是border-box,用於設置元素四個方向的邊框樣式,
最外層是margin-box,爲了讓元素與其他元素隔開,對於垂直方向上的BFC元素的margin會發生合併,去較大的值
padding-box和margin-box是透明的,padding-box會受元素的背景的影響,可以通過box-sizing設置
padding-box和border-box不能去負值,margin-box可以取負值
還有元素的溢出屬性,處理空白空間及文本溢出
* css中每個元素都看作多個盒子的組合,我們可以通過設置這些盒子的屬性來改變元素的樣式
* 如果設置 box-sizing 爲 content-box,那麼寬度就是內容區的寬度
* 如果設置爲 border-box,那麼寬度就死活內容區寬度+padding+border
複製代碼
單行文本溢出省略:
text-overflow:ellipsis; white-space:nowrap; overflow:hidden;
BFC
浮動,絕對定位,overflow不爲visible,非塊級盒子塊級容器
觸發:
1. float 除了none以外的值
 2. overflow 除了visible 以外的值(hidden,auto,scroll )
 3. display (table-cell,table-caption,inline-block, flex, inline-flex)
 4. position值爲(absolute,fixed)
特性:
在BFC中,盒子從頂端開始垂直地一個接一個地排列。
盒子垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰盒子垂直方向的margin會發生重疊。
在BFC中,每一個盒子的左外邊距(margin-left)會觸碰到容器的左外邊緣(border-left)。
BFC不會與浮動盒子產生交集,而是緊貼浮動元素邊緣。
計算BFC高度BFC時,自然也會檢測浮動的子盒子高度。
應用:
自適應兩欄佈局
解決margin疊加問題:下面元素添加父元素:overflow: hidden;
清除浮動,計算BFC高度
複製代碼
閉合浮動的辦法:
- 包含塊overflow:hidden/BFC
- 包含塊display:flow-root/BFC
- 包含塊變表格/BFC
- 包含塊變行內塊元素/BFC
- br標籤的清除浮動
談談你對MVVM開發模式的理解
- MVVM主要分爲model/view/viewmodel三部分
- model:代表數據模型,數據和業務邏輯都在model層中定義
- view:代表UI視圖,負責數據的展示
- viewmodel:負責監聽model中數據的改變並且控制視圖的更新,處理用戶交互操作
- Model和View並無直接關聯,是通過viewmodel來進行聯繫的,model和viewmodel之間有着雙向數據綁定的聯繫。因此當model中的數據改變時會觸發view層的刷新,同樣view中由用戶交互操作而改變的數據也會在model中同步。
- 這種模式實現了model和view的數據自動同步,因此開發者只需要專注於對數據的維護操作即可,而不需要自己操作DOM
如何優化SPA應用的首屏加載速度慢的問題
- 將公用的JS庫通過script標籤外部引入,讓瀏覽器並行下載資源文件,提高下載速度;
- 在配置路由時,頁面和組件使用懶加載的方式引入,在調用某個組件時再加載對應的js文件;
- 加一個首屏 loading 圖,提升用戶體驗;
跨域(Cross-Origin)
只要協議、主機、端口不一致,就會有跨域的問題
- javascript跨域通信
- jsonp
- CORS設置跨域頭
- 在框架中配置跨域代理
- jsonp的實現原理
- script標籤引入外部網站的代碼,一般都是使用查詢字符串告訴對方我們頁面中的callback函數,然後對方把需要返回的數據包在這個函數裏面
- 其實JSONP並不算真正意義上的AJAX請求,只是請求了一個js文件並且執行了,而且這種跨域方法只能進行GET請求
function jsonp(url, value, cb) {
let cbName = 'JSONP_CALLBACK_' + Date.now() + '_' + Math.random().toString().slice(2)
window[cbName] = cb
url = url + '?q=' + value + '&callback=' + cbName
let script = document.createElement('script')
script.src = url
script.onload = () => {
document.body.removeChild(script)
delete window[cbName]
}
document.body.appendChild(script)
}
function ajax(url = '', data = {}, type = 'GET') {
if (type === "GET") {
let urlStr = ""
Object.keys(data).forEach(key => {
urlStr += key + '=' + data[key] + '&'
})
if (urlStr) {
urlStr = urlStr.substring(0, urlStr.length - 1)
url += '?' + urlStr
}
return axios.get(url)
} else if (type === "POST") {
return axios.post(url, data)
}
}
複製代碼
- CORS
- 它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制
- 簡單請求
- 請求方法爲HEAD、GET或者POST中的一種
- HTTP的頭信息有以下幾種字段Accept、Accept-Language、Content-Language、Last-Event-ID
- Content-Type的值只限於application/x-www-form-urlencoded、multipart/form-data、text/plain三個
- 瀏覽器發出請求時,瀏覽器會自動在請求頭中添加一個字段Origin,值爲發出請求網頁的源地址
- 服務端根據這個值,決定是否同意這次請求,如果Origin的值不在指定的許可範圍,瀏覽器接收到的HTTP迴應將不包含Access-Control-Allow-Origin,拋出錯誤被XMLHttpRequest的onerror回調函數捕獲。如果Access-Control-Allow-Origin字段正好跟帶過去的Origin的值一樣,則返回對應的數據,完成一次請求。
- 非簡單請求以及option請求
- 非簡單請求是那種對服務器有特殊要求的請求,比如請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json。
- 在進行非簡單請求之前,瀏覽器會在正式請求之前發送一次預檢請求,這就是有時候我們會在控制檯中看到的option請求,就是說,正式請求之前,瀏覽器會去問服務端我這個地址能不能訪問你,如果可以,瀏覽器纔會發送正式的請求,否則報錯。
- 總結
- CORS實現跨域的方法就是根據請求頭的Origin值和響應頭的Access-Control-Request-Headers和Access-Control-Request-Method的值進行比對,通過了就可以請求成功,沒通過就請求失敗。
- 比較
- JSONP只支持GET請求,CORS支持所有類型的HTTP請求。JSONP的優勢在於支持老式瀏覽器,以及可以向不支持CORS的網站請求數據。
前端如何優化網站性能
- 減少 HTTP 請求數量:
- 瀏覽器與服務器主要是通過 HTTP 進行通信。瀏覽器與服務器需要經過三次握手,每次握手需要花費大量時間。而且不同瀏覽器對資源文件併發請求數量有限,一旦 HTTP 請求數量達到一定數量,資源請求就存在等待狀態,因此減少 HTTP 的請求數量可以很大程度上對網站性能進行優化。
- CSS Sprites:
- 國內俗稱 CSS 精靈,這是將多張圖片合併成一張圖片達到減少 HTTP 請求的一種解決方案,可以通過 CSS background 屬性來訪問圖片內容。這種方案同時還可以減少圖片總字節數。
- 合併 CSS 和 JS 文件:
- 現在前端有很多工程化打包工具,如:grunt、gulp、webpack等。爲了減少 HTTP 請求數量,可以通過這些工具再發布前將多個 CSS 或者 多個 JS 合併成一個文件。
- 採用 lazyLoad:
- 俗稱懶加載,可以控制網頁上的內容在一開始無需加載,不需要發請求,等到用戶操作真正需要的時候立即加載出內容。這樣就控制了網頁資源一次性請求數量。
- 利用瀏覽器緩存
- 瀏覽器緩存是將網絡資源存儲在本地,等待下次請求該資源時,如果資源已經存在就不需要到服務器重新請求該資源,直接在本地讀取該資源。
- 減少 DOM 操作,達到減少重排(Reflow)
- 基本原理:重排是 DOM 的變化影響到了元素的幾何屬性(寬和高),瀏覽器會重新計算元素的幾何屬性,會使渲染樹中受到影響的部分失效,瀏覽器會驗證 DOM 樹上的所有其它結點的 visibility 屬性,這也是 Reflow 低效的原因。如果 Reflow 的過於頻繁,CPU 使用率就會急劇上升。
Less / Sass
Less的變量名使用@符號開始 Sass的變量是必須$開始
- 作用域:
- Sass無全局變量概念
- LESS中的作用域和其他程序語言中的作用域非常的相同
- 混合(Mixins):
- Sass
聲明:@mixin a($borderWidth:2px){} 調用:@include error(); 複製代碼
- Less
聲明:.error(@borderWidth:2px){} 調用:.error(); 複製代碼
- 繼承
- Sass
@extend .block; /*繼承.block選擇器下所有樣式*/ 複製代碼
- Less
.block;/*繼承.block選擇器下所有樣式*/ 複製代碼
AntDesign / bootstrap
http協議
- HTTP是基於TCP/IP通信協議來傳遞數據
- HTTP是一個應用層協議,由請求和響應構成,是一個標準的客戶端服務器模型。HTTP是一個無狀態的協議。
- 工作過程大概如下:
- 用戶在瀏覽器中鍵入需要訪問網頁的URL或者點擊某個網頁中鏈接;
- 瀏覽器根據URL中的域名,通過DNS解析出目標網頁的IP地址;
- 在HTTP開始工作前,客戶端首先會通過TCP/IP協議來和服務端建立鏈接(TCP三次握手)
- 建立連接後,客戶機發送一個請求給服務器,請求方式的格式爲:統一資源標識符(URL)、協議版本號,後邊是MIME信息包括請求修飾符、客戶機信息和可內容。
- 服務器接到請求後,給予相應的響應信息,其格式爲一個狀態行,包括信息的協議版本號、一個成功或錯誤的代碼,後邊是MIME信息包括服務器信息、實體信息和可能的內容。
- 一般情況下,一旦Web服務器向瀏覽器發送了請求數據,它就要關閉TCP連接,然後如果瀏覽器或者服務器在其頭信息加入了這行代碼:Connection:keep-alive,TCP連接在發送後將仍然保持打開狀態,於是,瀏覽器可以繼續通過相同的連接發送請求。保持連接節省了爲每個請求建立新連接所需的時間,還節約了網絡帶寬。
- 短連接:建立連接——數據傳輸——關閉連接...建立連接——數據傳輸——關閉連接,如果客戶請求頻繁,將在TCP的建立和關閉操作上浪費較多時間和帶寬。
- 長連接:建立連接——數據傳輸...(保持連接)...數據傳輸——關閉連接
- with pipeling: 每次建立鏈接後無需等待請求回來就可以發送下一個請求
- without pipeling: 客戶端只在收到前一個請求的響應後,才發出新的請求。
- Http請求報文
客戶端發送一個HTTP請求到服務器的請求消息包括以下格式: 請求行(request line)、請求頭部(header)、請求體組成 請求行: 方法: GET 獲取資源 POST 向服務器端發送數據,傳輸實體主體 PUT 傳輸文件 HEAD 獲取報文首部 DELETE 刪除文件 OPTIONS 詢問支持的方法 TRACE 追蹤路徑 URL 協議/版本號 請求頭: 通用首部(General Header) 請求首部(Request Header) 響應首部(Response Header) 實體首部(Entity Header Fields) 請求體 複製代碼
- Http響應報文
HTTP響應組成:響應行、響應頭、響應體。 響應行 (HTTP/1.1)表明HTTP版本爲1.1版本,狀態碼爲200,狀態消息爲(ok) 響應頭 Date:生成響應的日期和時間; Content-Type:指定了MIME類型的HTML(text/html),編碼類型是ISO-8859-1 響應體 複製代碼
- GET和POST區別
- GET提交的數據會放在URL之後,以?分割URL和傳輸數據,參數之間以&相連,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的數據放在HTTP包的Body中.
- GET提交的數據大小有限制(因爲瀏覽器對URL的長度有限制),而POST方法提交的數據沒有限制.
- GET方式需要使用Request.QueryString來取得變量的值,而POST方式通過Request.Form來獲取變量的值。
- GET方式提交數據,會帶來安全問題,比如一個登錄頁面,通過GET方式提交數據時,用戶名和密碼將出現在URL上,如果頁面可以被緩存或者其他人可以訪問這臺機器,就可以從歷史記錄獲得該用戶的賬號和密碼.
websocket
首先Websocket是基於HTTP協議的,或者說借用了HTTP的協議來完成一部分握手。
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
複製代碼
-
http long poll 和 ajax 輪詢都可以實現實時信息傳遞
- ajax輪詢: 讓瀏覽器隔個幾秒就發送一次請求,詢問服務器是否有新信息。
- long poll 都是採用輪詢的方式,不過採取的是阻塞模型,客戶端發起連接後,如果沒消息,就一直不返回Response給客戶端。直到有消息才返回,返回完之後,客戶端再次建立連接,周而復始
-
特點:
- 解決了http協議只能從客戶端向服務器發送請求的缺陷,有了websocket,服務器也能主動向客戶端推送消息
- 和http一樣,是建立在tcp協議之上,默認端口也是80和443,
- 沒有同源限制,客戶端可以與任意服務器通信
- 協議標識符是ws,服務器網址就是URL
- 可以發送文本,也可以發送二進制數據
socket.io
socket.io 是一個能實現多人遠程實時通信(聊天)的庫 它包裝的是 H5, WebSocket和輪詢, 如果是較新的瀏覽器內部使用 WebSocket,如果瀏覽器不支持, 那內部就會使用輪詢實現實時通信
網頁從輸入網址到渲染完成經歷了哪些過程
1 輸入網址 2 發送到DNS服務器,並獲取域名對應的web服務器對應的ip地址 3 與web服務器建立TCP連接 4 瀏覽器向web服務器發送http請求 5 web服務器響應請求,並返回指定url的數據(或錯誤信息,或重定向的新的url地址) 6 瀏覽器下載web服務器返回的數據及解析html源文件 7 生成DOM樹,解析css和js,渲染頁面,直至顯示完成
數據結構和算法
// reduce
function reduce(ary, f, initVal) {
var start = 0
if (arguments.length == 2) {
initVal = ary[0]
start = 1
}
for (var i = start; i < ary.length; i++) {
initVal = f(initVal, ary[i], i, ary)
}
return initVal
}
// flattenDeep
function flattenDeep(ary) {
return [].concat(...ary.map(val => {
if (Array.isArray(val)) {
return flattenDeep(val)
} else {
return val
}
}))
}
複製代碼
ES6 新特性
- 函數默認值
- 模板字符串:
123${a}456
,\ - 解構賦值
- let & const
- let 無變量提升,有塊級作用域,禁止重複聲明
- const 無變量提升,有塊級作用域,禁止重複聲明,禁止重複賦值
- 新增庫函數
- Number .EPSILON / .isInteger / .isInteger
- String .includes / .repeat / .startsWith / .endsWith
- Array .fill / .findIndex / .of() /
- Object .assign
- Math
- 箭頭函數:共享父級 this 對象,共享父級 arguments,不能當做構造函數
- 類 & 繼承
- 本質爲對原型鏈的二次包裝;類沒有提升;不能使用字面量定義屬性;動態繼承類的構造方法中 super 優先 this
- 模塊
- 每個模塊都有自己完全獨立的代碼塊,跟作用域類似,但是更加封閉。
- 無限制導出導出
- 內聯導出:嚴格模式下運行使用 export 關鍵字,後面緊跟聲明關鍵字(let、function 等)聲明一個導出對象,聲明並同時導出的導出方式
- 對象導出
- 一個模塊只能有一個默認導出
ES8 新特性
- String:新增padStart,padEnd
- Object.values 方法返回一個給定對象自己的所有可枚舉屬性值的數組
- Object.entries 方法返回一個給定對象自身可遍歷屬性 [key, value] 的數組
- Object.getOwnPropertyDescriptors 方法返回指定對象所有自身屬性的描述對象
- 函數參數和函數調用中的尾逗號
- Async 函數
BOM / DOM
- DOM文檔對象模型,BOM瀏覽器對象模型
- DOM 是針對 HTML 和 XML 提供的一個API,爲了能以編程的方法操作這個 HTML 的內容。將html中的每個元素都看作是一個對象,每個對象都叫做一個節點,這些節點組成一個DOM樹。document是DOM樹的根節點
- BOM 是瀏覽器提供的附加對象,用於處理文檔之外的所有內容,比如alert/confirm/prompt,BOM包含的對象有,document,screen,location,history,navigator
- DOM是所有W3C標準都必須遵守的規則,BOM是各瀏覽器廠商遵守的規則
- BOM的核心是window,它既是通過js訪問瀏覽器窗口的一個接口,又是一個Global(全局)對象。這意味着在網頁中定義的任何對象,變量和函數,都以window作爲其global對象。
- DOM通過創建樹來表示文檔,描述了處理網頁內容的方法和接口,從而使開發者對文檔的內容和結構具有控制力,用DOM API可以輕鬆地刪除、添加和替換節點。
- DOM 的根節點是BOM 的window 對象的子對象。
圖片懶加載
- 三個API,我們獲得了三個值:
- 可視區高度clientHeight、
- 元素相對於其父元素容器頂部的距離offsetTop、
- 瀏覽器窗口頂部與容器元素頂部的距離也就是滾動條滾動的高度scrollTop。
- 當offsetTop - scroolTop < clientHeight,則圖片進入了可視區內,則被請求。
var imgs = document.querySelectorAll('img');
//offsetTop是元素與offsetParent的距離,循環獲取直到頁面頂部
function getTop(e) {
var T = e.offsetTop;
while(e = e.offsetParent) {
T += e.offsetTop;
}
return T;
}
function lazyLoad(imgs) {
var H = document.documentElement.clientHeight;//獲取可視區域高度
var S = document.documentElement.scrollTop || document.body.scrollTop;
for (var i = 0; i < imgs.length; i++) {
if (H + S > getTop(imgs[i])) {
imgs[i].src = imgs[i].getAttribute('data-src');
}
}
}
window.onload = window.onscroll = function () { //onscroll()在滾動條滾動的時候觸發
lazyLoad(imgs);
}
複製代碼
原型,閉包,高級函數,異步
- 閉包就是一個函數裏面生成並返回一個函數,返回的這個函數能讀取到外部函數裏面的變量
- 原型就是 a 是實例,b 是構造函數,然後a.proto === b.prototype,使用instanceof來判斷的時候就是不停地向上尋找,還有讀取a的某個屬性如果沒有,就會默認去a的原型上找
- 高階函數:高階函數是一個接收函數作爲參數或將函數作爲輸出返回的函數 map/reduce/filter
- 異步:js是單線程的,但瀏覽器是多線程的,當js運行遇到異步代碼時,會將代碼交給webapi異步執行,js則可以繼續執行下面的代碼;異步代碼會被塞入task queue裏排隊,task queue會一直觀察棧裏代碼有沒有執行完成,一旦發現棧空了,就會調用回調函數,然後重新回到js線程中執行
- www.zhihu.com/search?type…
- async表示該函數要做異步處理。await表示後面的代碼是一個異步操作,等待該異步操作完成後再執行後面的動作。如果異步操作有返回的數據,則在左邊用一個變量來接收它。
sessionstorage localstorage cookie區別
- 傳遞方式不同 cookie數據始終在同源的http請求中攜帶(即使不需要),即cookie在瀏覽器和服務器間來回傳遞。 sessionStorage和loaclStorage不會自動把數據發給服務器,僅在本地保存。
- 數據大小不同 cookie數據還有路徑(path)的概念,可以限制cookie只屬於某個路徑下。 cookie數據最大4k,sessionStorage和localStorage比cookie大得多,可以達到5M或者更大。
- 數據有效期不同 sessionStorage:僅在當前瀏覽器窗口關閉前有效,自然也就不可能持久保持; localStorage:始終有效,窗口或瀏覽器關閉也一直保存,因此用作持久數據; cookie只在設置cookie過期時間之前一直有效,即使窗口或瀏覽器關閉。
- 作用域不同 sessionStorage不同的瀏覽器窗口不能共享,即使是同一個頁面; localStorage所有同源窗口都是共享的; cookie所有同源窗口中都是共享的。
session / cookie
-
Cookie 可以保持登錄信息到用戶下次與服務器的會話,換句話說,下次訪問同一網站時,用戶會發現不必輸入用戶名和密碼就已經登錄了(當然,不排除用戶手工刪除Cookie),Cookie滿足同源策略 Cookie 在生成時就會被指定一個Expire值,這就是Cookie的生存週期,在這個週期內Cookie有效,超出週期Cookie就會被清除。有些頁面將Cookie的生存週期設置爲“0”或負值,這樣在關閉瀏覽器時,就馬上清除Cookie,不會記錄用戶信息,更加安全。
-
由於HTTP協議是無狀態的協議,所以服務端需要記錄用戶的狀態時,就需要用某種機制來識具體的用戶,這個機制就是Session.典型的場景比如購物車,當你點擊下單按鈕時,由於HTTP協議無狀態,所以並不知道是哪個用戶操作的,所以服務端要爲特定的用戶創建了特定的Session,用用於標識這個用戶,並且跟蹤用戶,這樣才知道購物車裏面有幾本書。這個Session是保存在服務端的,有一個唯一標識。
-
Session是在服務端保存的一個數據結構,用來跟蹤用戶的狀態,這個數據可以保存在集羣、數據庫、文件中; Cookie是客戶端保存用戶信息的一種機制,用來記錄用戶的一些信息,也是實現Session的一種方式。
event loop
第一步確認宏任務,微任務
宏任務:script,setTimeout,setImmediate,promise中的executor
微任務:promise.then,process.nextTick
process.nextTick優先級高於Promise.then
timers: setTimeout / setInterval
I/O callbacks: 不在其他階段的所有回調函數
poll: 獲取新的I/O事件
check:執行setImmediate
close callback: 執行關閉事件的回調函數
在整個輪詢的開始執行process.nextTick
然後再執行setTimeOut、setInterval
再執行其他的回調函數
最後執行setImmediate
複製代碼
發送ajax請求
axios / fetch
複製代碼
Node.js
Node核心思想:1.非阻塞;  2.單線程;  3.事件驅動。
Node 是一個服務器端 JavaScript 解釋器
當線程遇到IO操作的時候,不會以阻塞的方式等待IO操作完成或者數據的返回,而是將IO操作發送給操作系統,
然後接着執行下一個操作,當操作系統執行完IO操作之後,以事件的方式通知執行IO的線程,
線程會在特定的時候執行這個事件。這一切的前提條件就是,系統需要一個事件循環,
以不斷的去查詢有沒有未處理的事件,然後給預處理。
複製代碼
Redux
redux 是一個獨立的專門用於狀態管理的js庫
可以管理react應用中多個組件共享的狀態
用redux對組件的狀態進行集中式管理
組件:兩個方面
展現數據 狀態顯示
與用戶交互更新數據 更新狀態
redux核心是一個store(倉庫)
組件直接從store中讀取狀態
更新狀態:
1. Action Creators ==>> dispatch(action) :傳兩個值(type和data) type是傳的類型(刪除,增加,創建,更新)
2. store
3. Reducers ==>> 接受(previousState, action) 返回(newState)
4. React Component
createStore()
store: 管理state, reducer
方法: getState() , dispatch(action) , subscribe(listener)
action對象
reducer返回的是新的狀態
applyMiddleware 中間件
thunk 異步
複製代碼
diff算法
- 只在同層進行比較
- 如果節點發生變化,那麼就直接替換
- 如果節點相同,遞歸比較子節點的變化
- 如果有key,那麼就會key相同的進行比較
react-redux 的核心就是一個connect函數,接收兩個參數,mapStatetoprops,mapdispatchtoprops,返回一個高階組件,這個高階組件接受一個組件,返回一個組件,但是這個返回的組件的props上面多了數據以及操作數據的方法
function connect(mapStateToProps,mapDispatchToProps){
return function(com){
return class extends React.Component{
render(){
return (
<Consumer>
{store=>{
state = mapStateToProps(store.getState())
dispatch = mapDispatchToProps(store.dispatch)
return <Comp {...state}{...dispatch}></Comp>
}}
</Consumer>
) }
}
}
}
複製代碼
容器組件和展示組件
- 容器組件負責管理數據和邏輯
- 展示組件負責UI的呈現
- 他們通過react-redux提供的connect方法取得聯繫
爲什麼連接的時候是三次握手,關閉的時候卻是四次握手?
因爲當Server端收到Client端的SYN連接請求報文後,可以直接發送SYN+ACK報文。 其中ACK報文是用來應答的,SYN報文是用來同步的。 但是關閉連接時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET, 所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。 只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步握手。
- 三次揮手:
- 客戶端發送 SYN 包到服務端,等待服務端確認
- 服務端收到 SYN 包,同時自己也發送一個 SYN+ACK 包給客戶端
- 客戶端接收到 SYN+ACK 包,向服務端發送確認包 ACK ,發送完畢,客戶端與服務端 TCP 連接成功,完成三次握手
- 四次揮手:
- 客戶端連續發送釋放報文 FIN ,等待服務端確認
- 服務端收到釋放報文 FIN ,發出確認報文 ACK
redux
action: 是store唯一的信息來源,把action發送給store必須通過store的dispatch方法。
每個action必須有一個type屬性描述action的類型。
複製代碼
XSS 與 CSRF 兩種跨站攻擊
- xss 跨站腳本攻擊,主要是前端層面的,用戶在輸入層面插入攻擊腳本,改變頁面的顯示,或則竊取網站 cookie,預防方法:不相信用戶的所有操作,對用戶輸入進行一個轉義,不允許 js 對 cookie 的讀寫
- csrf 跨站請求僞造,以你的名義,發送惡意請求,通過 cookie 加參數等形式過濾
- 我們沒法徹底杜絕攻擊,只能提高攻擊門檻
負載均衡
當系統面臨大量用戶訪問,負載過高的時候,通常會使用增加服務器數量來進行橫向擴展,使用集羣和負載均衡提高整個系統的處理能力
JS實現繼承的方法
1. 原型鏈繼承
將父類的實例作爲子類的原型
function Cat() {}
Cat.prototype = new Animal()
Cat.prototype.name = 'cat'
var cat = new Cat()
2. 構造繼承
使用父類的構造函數來增強子類的實例,等於是複製父類的實例屬性給子類
function Cat(name) {
Animal.call(this)
instance.name = name || 'Tom'
}
var cat = new Cat()
3. 實例繼承
爲父類實例添加新特性,作爲子類的實例返回
function Cat(name) {
var instance = new Animal()
instance.name = name || 'Tom'
return instance
}
var cat = new Cat()