腦子裏陸陸續續過出來的一些面試題,文章會不斷更新javascript
注:「固定」這個詞的含義,它指的固定是指只要傳進去了 context,則 bind 中 return 出來的函數 this 便一直指向 context,除非 context 是個變量 6. 變量聲明提高:js 代碼在運行前都會進行 AST 解析,函數申明默認會提到當前做用域最前面,變量申明也會進行提高。但賦值不會獲得提高。關於 AST 解析,這裏也能夠說是造成詞法做用域的主要緣由css
這裏若是面試官問到2,3,4,5,6中的一點,你可以把2,3,4,5,6整理到一塊兒,串聯起來進行統一的回答效果極佳html
具體參考 從指向看JavaScriptvue
詳細參考 my-promisejava
function
關鍵字與函數名之間有一個星號;yield
表達式,定義不一樣的內部狀態;next
指針移向下一個狀態這裏你能夠說說 Generator
的異步編程,以及它的語法糖 async
和 awiat
,傳統的異步編程。ES6 以前,異步編程大體以下node
傳統異步編程方案之一:協程,多個線程互相協做,完成異步任務。react
基本用法webpack
async function timeout (ms) {
await new Promise((resolve) => {
setTimeout(resolve, ms)
})
}
async function asyncConsole (value, ms) {
await timeout(ms)
console.log(value)
}
asyncConsole('hello async and await', 1000)
複製代碼
注:最好把2,3,4 連到一塊兒講css3
/* 方案1 */
.left {
width: 120px;
float: left;
}
.right {
margin-left: 120px;
}
/* 方案2 */
.left {
width: 120px;
float: left;
}
.right {
width: calc(100% - 120px);
float: left;
}
複製代碼
.wrap {
width: 100%;
height: 200px;
}
.wrap > div {
height: 100%;
}
/* 方案1 */
.left {
width: 120px;
float: left;
}
.right {
float: right;
width: 120px;
}
.center {
margin: 0 120px;
}
/* 方案2 */
.left {
width: 120px;
float: left;
}
.right {
float: right;
width: 120px;
}
.center {
width: calc(100% - 240px);
margin-left: 120px;
}
/* 方案3 */
.wrap {
display: flex;
}
.left {
width: 120px;
}
.right {
width: 120px;
}
.center {
flex: 1;
}
複製代碼
/* 方案1 */
.wrap {
text-align: center
}
.center {
display: inline;
/* or */
/* display: inline-block; */
}
/* 方案2 */
.center {
width: 100px;
margin: 0 auto;
}
/* 方案2 */
.wrap {
position: relative;
}
.center {
position: absulote;
left: 50%;
transform: translateX(-50%);
}
複製代碼
/* 定高方案1 */
.center {
height: 100px;
margin: 50px 0;
}
/* 定高方案2 */
.center {
height: 100px;
position: absolute;
top: 50%;
margin-top: -25px;
}
/* 不定高方案1 */
.center {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
/* 不定高方案2 */
.wrap {
display: flex;
align-items: center;
}
.center {
width: 100%;
}
/* 不定高方案3 */
/* 設置 inline-block 則會在外層產生 IFC,高度設爲 100% 撐開 wrap 的高度 */
.wrap::before {
content: '';
height: 100%;
display: inline-block;
vertical-align: middle;
}
.wrap {
text-align: center;
}
.center {
display: inline-block;
vertical-align: middle;
}
複製代碼
延伸: box-sizingnginx
float 的值不爲 none。
overflow 的值不爲 visible。
position 的值不爲 relative 和 static。
display 的值爲 table-cell, table-caption, inline-block中的任何一個。
用處?常見的多欄佈局,結合塊級別元素浮動,裏面的元素則是在一個相對隔離的環境裏運行。
IFC中的line box通常左右都貼緊整個 IFC,可是會由於 float 元素而擾亂。float 元素會位於 IFC 與 line box 之間,使得 line box 寬度縮短。 同個 ifc 下的多個 line box 高度會不一樣。 IFC 中時不可能有塊級元素的,當插入塊級元素時(如 p 中插入 div )會產生兩個匿名塊與 div 分隔開,即產生兩個 IFC ,每一個 IFC 對外表現爲塊級元素,與 div 垂直排列。
用處?
水平居中:當一個塊要在環境中水平居中時,設置其爲 inline-block 則會在外層產生IFC,經過 text-align 則可使其水平居中。
垂直居中:建立一個 IFC,用其中一個元素撐開父元素的高度,而後設置其 vertical-align: middle,其餘行內元素則能夠在此父元素下垂直居中
詳細細節參考 實現一個屬於咱們本身的簡易MVVM庫
擴充:如何監聽數組變化
詳細請參考 實現Virtual Dom && Diff
補充1:VDOM 的必要性?
建立真實DOM的代價高:真實的 DOM 節點 node 實現的屬性不少,而 vnode 僅僅實現一些必要的屬性,相比起來,建立一個 vnode 的成本比較低。
觸發屢次瀏覽器重繪及迴流:使用 vnode ,至關於加了一個緩衝,讓一次數據變更所帶來的全部 node 變化,先在 vnode 中進行修改,而後 diff 以後對全部產生差別的節點集中一次對 DOM tree 進行修改,以減小瀏覽器的重繪及迴流。
補充2:vue 爲何採用 vdom?
引入 Virtual DOM 在性能方面的考量僅僅是一方面。
性能受場景的影響是很是大的,不一樣的場景可能形成不一樣實現方案之間成倍的性能差距,因此依賴細粒度綁定及 Virtual DOM 哪一個的性能更好還真不是一個容易下定論的問題。
Vue 之因此引入了 Virtual DOM,更重要的緣由是爲了解耦 HTML 依賴,這帶來兩個很是重要的好處是:
綜上,Virtual DOM 在性能上的收益並非最主要的,更重要的是它使得 Vue 具有了現代框架應有的高級特性。
上面提到的每一個點,具體細節還得看本身的理解
延伸1:img iframe script 來發送跨域請求有什麼優缺點?
優勢:跨域完畢以後DOM操做和互相之間的JavaScript調用都是沒有問題的
缺點:1.若結果要以URL參數傳遞,這就意味着在結果數據量很大的時候須要分割傳遞,巨煩。2.還有一個是iframe自己帶來的,母頁面和iframe自己的交互自己就有安全性限制。
優勢:能夠直接返回json格式的數據,方便處理
缺點:只接受GET請求方式
優勢:能夠訪問任何url,通常用來進行點擊追蹤,作頁面分析經常使用的方法
缺點:不能訪問響應文本,只能監聽是否響應
延伸2:配合 webpack 進行反向代理?
webpack 在 devServer 選項裏面提供了一個 proxy 的參數供開發人員進行反向代理
'/api': {
target: 'http://www.example.com', // your target host
changeOrigin: true, // needed for virtual hosted sites
pathRewrite: {
'^/api': '' // rewrite path
}
},
複製代碼
而後再配合 http-proxy-middleware
插件對 api 請求地址進行代理
const express = require('express');
const proxy = require('http-proxy-middleware');
// proxy api requests
const exampleProxy = proxy(options); // 這裏的 options 就是 webpack 裏面的 proxy 選項對應的每一個選項
// mount `exampleProxy` in web server
const app = express();
app.use('/api', exampleProxy);
app.listen(3000);
複製代碼
而後再用 nginx
把容許跨域的源地址添加到報頭裏面便可
說到 nginx
,能夠再談談 CORS 配置,大體以下
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'DNT, X-Mx-ReqToken, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type';
add_header 'Access-Control-Max-Age' 86400;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 200;
}
}
複製代碼
http協議無狀態中的 狀態 到底指的是什麼?!
【狀態】的含義就是:客戶端和服務器在某次會話中產生的數據
那麼對應的【無狀態】就意味着:這些數據不會被保留
but
首先得明確 http 緩存的好處
常見 http 緩存的類型
而後談談本地緩存
本地緩存是指瀏覽器請求資源時命中了瀏覽器本地的緩存資源,瀏覽器並不會發送真正的請求給服務器了。它的執行過程是:
與本地緩存相關的頭有:Cache-Control、Expires,Cache-Control有多個可選值表明不一樣的意義,而Expires就是一個日期格式的絕對值。
Cache-Control
Cache-Control是HTPP緩存策略中最重要的頭,它是HTTP/1.1中出現的,它由以下幾個值
例如:
Cache-Control: public, max-age=1000
複製代碼
表示資源能夠被全部用戶以及代理服務器緩存,最長時間爲1000秒。
Expires
Expires是HTTP/1.0出現的頭信息,一樣是用於決定本地緩存策略的頭,它是一個絕對時間,時間格式是如Mon, 10 Jun 2015 21:31:12 GMT,只要發送請求時間是在Expires以前,那麼本地緩存始終有效,不然就會去服務器發送請求獲取新的資源。若是同時出現Cache-Control:max-age和Expires,那麼max-age優先級更高。他們能夠這樣組合使用
Cache-Control: public
Expires: Wed, Jan 10 2018 00:27:04 GMT
複製代碼
所謂的緩存協商
當第一次請求時服務器返回的響應頭中存在如下狀況時
那麼瀏覽器第二次請求時就會與服務器進行協商,詢問瀏覽器中的緩存資源是否是舊版本,需不須要更新,此時,服務器就會作出判斷,若是緩存和服務端資源的最新版本是一致的,那麼就無需再次下載該資源,服務端直接返回304 Not Modified 狀態碼,若是服務器發現瀏覽器中的緩存已是舊版本了,那麼服務器就會把最新資源的完整內容返回給瀏覽器,狀態碼就是200 Ok,那麼服務端是根據什麼來判斷瀏覽器的緩存是否是最新的呢?實際上是根據HTTP的另外兩組頭信息,分別是:Last-Modified/If-Modified-Since 與 ETag/If-None-Match。
Last-Modified 與 If-Modified-Since
若是二者相等或者大於服務器上的最新修改時間,那麼表示瀏覽器的緩存是有效的,此時緩存會命中,服務器就再也不返回內容給瀏覽器了,同時Last-Modified頭也不會返回,由於資源沒被修改,返回了也沒什麼意義。若是沒命中緩存則最新修改的資源連同Last-Modified頭一塊兒返回。
第一次請求返回的響應頭:
Cache-Control:max-age=3600
Expires: Fri, Jan 12 2018 00:27:04 GMT
Last-Modified: Wed, Jan 10 2018 00:27:04 GMT
複製代碼
第二次請求的請求頭信息:
If-Modified-Since: Wed, Jan 10 2018 00:27:04 GMT
複製代碼
這組頭信息是基於資源的修改時間來判斷資源有沒有更新,另外一種方式就是根據資源的內容來判斷,就是接下來要討論的ETag與If-None-Match
ETag與If-None-Match
ETag/If-None-Match與Last-Modified/If-Modified-Since的流程實際上是相似的,惟一的區別是它基於資源的內容的摘要信息(好比MD5 hash)來判斷
瀏覽器發送第二次請求時,會把第一次的響應頭信息ETag的值放在If-None-Match的請求頭中發送到服務器,與最新的資源的摘要信息對比,若是相等,取瀏覽器緩存,不然內容有更新,最新的資源連同最新的摘要信息返回。用ETag的好處是若是由於某種緣由到時資源的修改時間沒改變,那麼用ETag就能區分資源是否是有被更新。
第一次請求返回的響應頭:
Cache-Control: public, max-age=31536000
ETag: "15f0fff99ed5aae4edffdd6496d7131f"
複製代碼
第二次請求的請求頭信息:
If-None-Match: "15f0fff99ed5aae4edffdd6496d7131f"
複製代碼
如今咱們常說的 「session」,是爲了繞開 cookie 的各類限制,一般藉助 cookie 自己和後端存儲實現的,一種更高級的會話狀態實現
session 的常見實現要藉助cookie來發送 sessionID
防範:記住一點 「全部用戶輸入都是不可信的」,因此得作輸入過濾和轉義
防範:用戶操做驗證(驗證碼),額外驗證機制(token使用)等
詳細點擊 對於跨站僞造請求(CSRF)的理解和總結
我的準備從新撿回本身的公衆號了,以後每週保證一篇高質量好文,感興趣的小夥伴能夠關注一波。