此文是上篇 如何拿到大廠offer面試題|技術徵文 下,更新下剩下題目及答題思路
1.請簡單描述http協議的請求報文和響應報文的組成格式?
HTTP請求報文
一個HTTP請求報文由請求行(request line)、請求頭部(header)、空行和請求資料4個部分組成,下圖給出了請求報文的一般格式。
英文:
<request-line>
<headers>
<blank line>
<request-body>
1.請求頭
請求行由請求方法欄位、URL欄位和HTTP協議版本欄位3個欄位組成,它們用空格分隔。例如,GET /index.html HTTP/1.1。
HTTP協議的請求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。
2.請求頭部
請求頭部由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號“:”分隔。請求頭部通知伺服器有關於客戶端請求的資訊,典型的請求頭有:
User-Agent:產生請求的瀏覽器型別。
Accept:客戶端可識別的內容型別列表。
Host:請求的主機名,允許多個域名同處一個IP地址,即虛擬主機。
3.空行
最後一個請求頭之後是一個空行,傳送回車符和換行符,通知伺服器以下不再有請求頭。
4.請求資料
請求資料不在GET方法中使用,而是在POST方法中使用。POST方法適用於需要客戶填寫表單的場合。與請求資料相關的最常使用的請求頭是Content-Type和Content-Length。
HTTP報文
HTTP響應也由三個部分組成,分別是:狀態行、訊息報頭、響應正文。
如下所示,HTTP響應的格式與請求的格式十分類似:
英文:
<status-line>
<headers>
<blank line>
<response-body>
正如你所見,在響應中唯一真正的區別在於第一行中用狀態資訊代替了請求資訊。狀態行(status line)通過提供一個狀態碼來說明所請求的資源情況。
狀態行格式如下:
HTTP-Version Status-Code Reason-Phrase CRLF
其中,HTTP-Version表示伺服器HTTP協議的版本;Status-Code表示伺服器發回的響應狀態程式碼;Reason-Phrase表示狀態程式碼的文字描述。狀態程式碼由三位數字組成,第一個數字定義了響應的類別,且有五種可能取值。
- 1xx:指示資訊--表示請求已接收,繼續處理。
- 2xx:成功--表示請求已被成功接收、理解、接受。
- 3xx:重定向--要完成請求必須進行更進一步的操作。
- 4xx:客戶端錯誤--請求有語法錯誤或請求無法實現。
- 5xx:伺服器端錯誤--伺服器未能實現合法的請求。
常見狀態程式碼、狀態描述的說明如下。
- 200 OK:客戶端請求成功。
- 400 Bad Request:客戶端請求有語法錯誤,不能被伺服器所理解。
- 401 Unauthorized:請求未經授權,這個狀態程式碼必須和WWW-Authenticate報頭域一起使用。
- 403 Forbidden:伺服器收到請求,但是拒絕提供服務。
- 404 Not Found:請求資源不存在,舉個例子:輸入了錯誤的URL。
- 500 Internal Server Error:伺服器發生不可預期的錯誤。
- 503 Server Unavailable:伺服器當前不能處理客戶端的請求,一段時間後可能恢復正常,舉個例子:HTTP/1.1 200 OK(CRLF)。
詳情可以參考該部落格
2.用三種方式實現塊框的垂直劇中效果,假設框的高度根據內容自適應
注意相容性,autoprefixer可以處理字首的相容而已,對於不支援transform和flex的瀏覽器,如果要相容該部分瀏覽器,請選擇其他方式(筆者做的大多是移動端,以下三種,除安卓4.3以下原生核心不支援外,並外見相容性的bug,flex在X5核心,ios低版本核心中有些相容性(如flex-wrap),需注意)。
第一種:flex
父元素設定以下屬性
display:flex;
flex-direction:row //web 預設的值,rn預設column
align-items:center複製程式碼
第二種:absolute
父元素設定
position:relative
本元素
position:absolute;
top:50%;
transform:translateY(-50%);
複製程式碼
第三種:利用display:table-cell屬性
display:table-cell;
vertical-alian:middle;複製程式碼
。。。還有很多
3.http中的狀態碼302代表的是什麼意思
302重定向表示臨時性轉移(Temporarily Moved ),當一個網頁URL需要短期變化時使用。
順便提一嘴301
301重定向/跳轉一般,表示本網頁永久性轉移到另一個地址。
301是永久性轉移(Permanently Moved),SEO常用的招式,會把舊頁面的PR等資訊轉移到新頁面
301重定向與302重定向的區別
301重定向是永久的重定向,搜尋引擎在抓取新內容的同時也將舊的網址替換為重定向之後的網址。
302重定向是臨時的重定向,搜尋引擎會抓取新的內容而保留舊的網址。因為伺服器返回302程式碼,搜尋引擎認為新的網址只是暫時的。
4.cookie是什麼,和session有什麼區別
1,session 在伺服器端,cookie 在客戶端(瀏覽器)
2,session 預設被存在在伺服器的一個檔案裡(不是記憶體)
3,session 的執行依賴 session id,而 session id 是存在 cookie 中的,也就是說,如果瀏覽
器禁用了 cookie ,同時 session 也會失效(但是可以通過其它方式實現,比如在 url 中傳遞
session_id)
4,session 可以放在 檔案、資料庫、或記憶體中都可以。
5,使用者驗證這種場合一般會用 session
因此,維持一個會話的核心就是客戶端的唯一標識,即 session id
5.有那些dom介面可以獲取一個元素的尺寸(寬度和高度)
假設該元素id為box
1.第一種通過內聯樣式(注意:css宣告中沒有設定hieght和width的話是獲取不到的,而且也不會根據box-sizing的值而返回不同盒子模型的寬高) var box = document.getElementById('box');
var w = box.style.width;
var h = box.style.height;複製程式碼
2.通過計算元素的大小(但是在ie情況下有一個問題,那就沒寫widht和height的css就返回auto,getComputedStyle在IE下如果設定了寬高為em這種單位,返回來的值依然是em,而不會是px);
var style = window.getComputedStyle ? window.getComputedStyle(box,null) : null || box.currentStyle;
var w = style.width;
var h = style.height;複製程式碼
3.offsetHeight和offsetHeight
4.getBoundingClientRect(IE67的left、top會少2px,並且沒有width、height屬性,需相容該部分瀏覽器的,那就不得不選擇放棄了)DOMRect 物件包含了一組用於描述邊框的只讀屬性——left、top、right和bottom,單位為畫素。除了 width 和 height 外的屬性都是相對於視口的左上角位置而言的
。。。
6.請描述dom事件的流程,即從觸發到結束的整個過程
事件流包括三個階段:事件捕獲階段、處於目標階段和事件冒泡階段。首先發生的是事件捕獲,
為截獲事件提供了機會。然後是實際的目標接收到事件。最後一個階段是冒泡階 段,可以在這
個階段對事件做出響應。 單擊<div>元素會按照如下圖:
DOM 事件流中,實際的目標(<div>元素)在捕獲階段不會接收到事件。這意味著在捕獲階段,
12 事件從 document 到<html>再到<body>後就停止了。下一個階段是“處於目標”階段,於是
事件在<div> 上發生,並在事件處理(後面將會討論這個概念)中被看成冒泡階段的一部分。然
後,冒泡階段發生, 事件又傳播迴文件。
多數支援 DOM 事件流的瀏覽器都實現了一種特定的行為;即使“DOM2 級事件”規範明確要求
捕獲階段不會涉及事件目標,但 IE9、Safari、Chrome、Firefox 和 Opera 9.5 及更高版本都
會在捕獲階段觸 發事件物件上的事件。結果,就是有兩個機會在目標物件上面操作事件。
以上是高程的內容。
7.請描述utf-8和unicode的區別
- Unicode 是「字符集」
- UTF-8 是「編碼規則」
Unicode是一套複雜的字元編碼標準,簡單來說就是將人類使用的每個所謂字元與一個非負整數對應,並且保證不同的字元對應的整數一定不同。UTF-8是這個整數的編碼方式,用1到4位元組來表達一個整數。
關係:UTF-8是Unicode的實現方式之一,它規定了字元如何在計算機中儲存、傳輸等。
8.講一講你在日常web開發中載入和互動體驗上常用的優化策略
1. 減少HTTP請求數
這條策略基本上所有前端人都知道,而且也是最重要最有效的。都說要減少HTTP請求,那請求多了到底會怎麼樣呢?首先,每個請求都是有成本的,既包 含時間成本也包含資源成本。一個完整的請求都需要經過DNS定址、與伺服器建立連線、傳送資料、等待伺服器響應、接收資料這樣一個“漫長”而複雜的過程。 時間成本就是使用者需要看到或者“感受”到這個資源是必須要等待這個過程結束的,資源上由於每個請求都需要攜帶資料,因此每個請求都需要佔用頻寬。
另外,由於瀏覽器進行併發請求的請求數是有上限的,因此請求數多了以後,瀏覽器需要分批進行請求,因此會增加使用者的等待時間,會給 使用者造成站點速度慢這樣一個印象,即使可能使用者能看到的第一屏的資源都已經請求完了,但是瀏覽器的進度條會一直存在。減少HTTP請求數的主要途徑包括:
(1). 從設計實現層面簡化頁面
如果你的頁面像百度首頁一樣簡單,那麼接下來的規則基本上都用不著了。保持頁面簡潔、減少資源的使用時最直接的。如果不是這樣,你的頁面需要華麗的皮膚,則繼續閱讀下面的內容。
(2). 合理設定HTTP快取
快取的力量是強大的,恰當的快取設定可以大大的減少HTTP請求。以有啊首頁為例,當瀏覽器沒有快取的時候訪問一共會發出78個請求,共600多K 資料(如圖1.1),而當第二次訪問即瀏覽器已快取之後訪問則僅有10個請求,共20多K資料(如圖1.2)。(這裡需要說明的是,如果直接F5重新整理頁面 的話效果是不一樣的,這種情況下請求數還是一樣,不過被快取資源的請求伺服器是304響應,只有Header沒有Body,可以節省頻寬)
怎樣才算合理設定?原則很簡單,能快取越多越好,能快取越久越好。例如,很少變化的圖片資源可以直接通過HTTP Header中的Expires設定一個很長的過期頭;變化不頻繁而又可能會變的資源可以使用Last-Modifed來做請求驗證。儘可能的讓資源能夠 在快取中待得更久。
(3). 資源合併與壓縮
如果可以的話,儘可能的將外部的指令碼、樣式進行合併,多個合為一個。另外,CSS、Javascript、Image都可以用相應的工具進行壓縮,壓縮後往往能省下不少空間。
(4). CSS Sprites
合併CSS圖片,減少請求數的又一個好辦法。
(5). Inline Images
使用data: URL scheme的方式將圖片嵌入到頁面或CSS中,如果不考慮資源管理上的問題的話,不失為一個好辦法。如果是嵌入頁面的話換來的是增大了頁面的體積,而且無法利用瀏覽器快取。使用在CSS中的圖片則更為理想一些。
(6). Lazy Load Images
這條策略實際上並不一定能減少HTTP請求數,但是卻能在某些條件下或者頁面剛載入時減少HTTP請求數。對於圖片而言,在頁面剛載入的時候可以只 載入第一屏,當使用者繼續往後滾屏的時候才載入後續的圖片。這樣一來,假如使用者只對第一屏的內容感興趣時,那剩餘的圖片請求就都節省了。有啊首頁曾經的做法 是在載入的時候把第一屏之後的圖片地址快取在Textarea標籤中,待使用者往下滾屏的時候才“惰性”載入。
2. 將外部指令碼置底
前文有談到,瀏覽器是可以併發請求的,這一特點使得其能夠更快的載入資源,然而外鏈指令碼在載入時卻會阻塞其他資源,例如在指令碼載入完成之前,它後面 的圖片、樣式以及其他指令碼都處於阻塞狀態,直到指令碼載入完成後才會開始載入。如果將指令碼放在比較靠前的位置,則會影響整個頁面的載入速度從而影響使用者體 驗。解決這一問題的方法有很多,而最簡單可依賴的方法就是將指令碼儘可能的往後挪,減少對併發下載的 影響。
3. 非同步執行inline指令碼
inline指令碼對效能的影響與外部指令碼相比,是有過之而無不及。首頁,與外部指令碼一樣,inline指令碼在執行的時候一樣會阻塞併發請求,除此之 外,由於瀏覽器在頁面處理方面是單執行緒的,當inline指令碼在頁面渲染之前執行時,頁面的渲染工作則會被推遲。簡而言之,inline指令碼在執行的時 候,頁面處於空白狀態。鑑於以上兩點原因,建議將執行時間較長的inline指令碼非同步執行,非同步的方式有很多種,例如使用script元素的defer屬 性(存在相容性問題和其他一些問題,例如不能使用document.write)、使用setTimeout,此外,在HTML5中引入了Web Workers的機制,恰恰可以解決此類問題。
4. Lazy Load Javascript
隨著Javascript框架的流行,越來越多的站點也使用起了框架。不過,一個框架往往包括了很多的功能實現,這些功能並不是每一個頁面都需要 的,如果下載了不需要的指令碼則算得上是一種資源浪費-既浪費了頻寬又浪費了執行花費的時間。目前的做法大概有兩種,一種是為那些流量特別大的頁面專門定製 一個專用的mini版框架,另一種則是Lazy Load。YUI則使用了第二種方式,在YUI的實現中,最初只載入核心模組,其他模組可以等到需要使用的時候才載入。
5. 將CSS放在HEAD中
如果將CSS放在其他地方比如BODY中,則瀏覽器有可能還未下載和解析到CSS就已經開始渲染頁面了,這就導致頁面由無CSS狀態跳轉到CSS狀 態,使用者體驗比較糟糕。除此之外,有些瀏覽器會在CSS下載完成後才開始渲染頁面,如果CSS放在靠下的位置則會導致瀏覽器將渲染時間推遲。
6. 減少不必要的HTTP跳轉
對於以目錄形式訪問的HTTP連結,很多人都會忽略連結最後是否帶’/',假如你的伺服器對此是區別對待的話,那麼你也需要注意,這其中很可能隱藏了301跳轉,增加了多餘請求。具體參見下圖,其中第一個連結是以無’/'結尾的方式訪問的,於是伺服器有了一次跳轉。
7. 避免重複的資源請求
這種情況主要是由於疏忽或頁面由多個模組拼接而成,然後每個模組中請求了同樣的資源時,會導致資源的重複請求。出現的機率不大,但是還是要注意排查。
。。。
9.什麼是CSRF攻擊,如何預防
CSRF全程 Cross Site Request Forgery, 跨站域請求偽造.CSRF是一種夾持使用者在已經登陸的web應用程式上執行非本意的操作的攻擊方式。相比於XSS,CSRF是利用了系統對頁面瀏覽器的信任,XSS則利用了系統對使用者的信任。
防禦CSRF攻擊:
目前防禦 CSRF 攻擊主要有三種策略:驗證 HTTP Referer 欄位;在請求地址中新增 token 並驗證;在 HTTP 頭中自定義屬性並驗證。
(1)驗證 HTTP Referer 欄位
根據 HTTP 協議,在 HTTP 頭中有一個欄位叫 Referer,它記錄了該 HTTP 請求的來源地址。在通常情況下,訪問一個安全受限頁面的請求來自於同一個網站,比如需要訪問 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,使用者必須先登陸 bank.example,然後通過點選頁面上的按鈕來觸發轉賬事件。這時,該轉帳請求的 Referer 值就會是轉賬按鈕所在的頁面的 URL,通常是以 bank.example 域名開頭的地址。而如果黑客要對銀行網站實施 CSRF 攻擊,他只能在他自己的網站構造請求,當使用者通過黑客的網站傳送請求到銀行時,該請求的 Referer 是指向黑客自己的網站。因此,要防禦 CSRF 攻擊,銀行網站只需要對於每一個轉賬請求驗證其 Referer 值,如果是以 bank.example 開頭的域名,則說明該請求是來自銀行網站自己的請求,是合法的。如果 Referer 是其他網站的話,則有可能是黑客的 CSRF 攻擊,拒絕該請求。
這種方法的顯而易見的好處就是簡單易行,網站的普通開發人員不需要操心 CSRF 的漏洞,只需要在最後給所有安全敏感的請求統一增加一個攔截器來檢查 Referer 的值就可以。特別是對於當前現有的系統,不需要改變當前系統的任何已有程式碼和邏輯,沒有風險,非常便捷。
然而,這種方法並非萬無一失。Referer 的值是由瀏覽器提供的,雖然 HTTP 協議上有明確的要求,但是每個瀏覽器對於 Referer 的具體實現可能有差別,並不能保證瀏覽器自身沒有安全漏洞。使用驗證 Referer 值的方法,就是把安全性都依賴於第三方(即瀏覽器)來保障,從理論上來講,這樣並不安全。事實上,對於某些瀏覽器,比如 IE6 或 FF2,目前已經有一些方法可以篡改 Referer 值。如果 bank.example 網站支援 IE6 瀏覽器,黑客完全可以把使用者瀏覽器的 Referer 值設為以 bank.example 域名開頭的地址,這樣就可以通過驗證,從而進行 CSRF 攻擊。
即便是使用最新的瀏覽器,黑客無法篡改 Referer 值,這種方法仍然有問題。因為 Referer 值會記錄下使用者的訪問來源,有些使用者認為這樣會侵犯到他們自己的隱私權,特別是有些組織擔心 Referer 值會把組織內網中的某些資訊洩露到外網中。因此,使用者自己可以設定瀏覽器使其在傳送請求時不再提供 Referer。當他們正常訪問銀行網站時,網站會因為請求沒有 Referer 值而認為是 CSRF 攻擊,拒絕合法使用者的訪問。
(2)在請求地址中新增 token 並驗證
CSRF 攻擊之所以能夠成功,是因為黑客可以完全偽造使用者的請求,該請求中所有的使用者驗證資訊都是存在於 cookie 中,因此黑客可以在不知道這些驗證資訊的情況下直接利用使用者自己的 cookie 來通過安全驗證。要抵禦 CSRF,關鍵在於在請求中放入黑客所不能偽造的資訊,並且該資訊不存在於 cookie 之中。可以在 HTTP 請求中以引數的形式加入一個隨機產生的 token,並在伺服器端建立一個攔截器來驗證這個 token,如果請求中沒有 token 或者 token 內容不正確,則認為可能是 CSRF 攻擊而拒絕該請求。
這種方法要比檢查 Referer 要安全一些,token 可以在使用者登陸後產生並放於 session 之中,然後在每次請求時把 token 從 session 中拿出,與請求中的 token 進行比對,但這種方法的難點在於如何把 token 以引數的形式加入請求。對於 GET 請求,token 將附在請求地址之後,這樣 URL 就變成 http://url?csrftoken=tokenvalue。 而對於 POST 請求來說,要在 form 的最後加上 <input type=”hidden” name=”csrftoken” value=”tokenvalue”/>,這樣就把 token 以引數的形式加入請求了。但是,在一個網站中,可以接受請求的地方非常多,要對於每一個請求都加上 token 是很麻煩的,並且很容易漏掉,通常使用的方法就是在每次頁面載入時,使用 javascript 遍歷整個 dom 樹,對於 dom 中所有的 a 和 form 標籤後加入 token。這樣可以解決大部分的請求,但是對於在頁面載入之後動態生成的 html 程式碼,這種方法就沒有作用,還需要程式設計師在編碼時手動新增 token。
該方法還有一個缺點是難以保證 token 本身的安全。特別是在一些論壇之類支援使用者自己發表內容的網站,黑客可以在上面釋出自己個人網站的地址。由於系統也會在這個地址後面加上 token,黑客可以在自己的網站上得到這個 token,並馬上就可以發動 CSRF 攻擊。為了避免這一點,系統可以在新增 token 的時候增加一個判斷,如果這個連結是鏈到自己本站的,就在後面新增 token,如果是通向外網則不加。不過,即使這個 csrftoken 不以引數的形式附加在請求之中,黑客的網站也同樣可以通過 Referer 來得到這個 token 值以發動 CSRF 攻擊。這也是一些使用者喜歡手動關閉瀏覽器 Referer 功能的原因。
(3)在 HTTP 頭中自定義屬性並驗證
這種方法也是使用 token 並進行驗證,和上一種方法不同的是,這裡並不是把 token 以引數的形式置於 HTTP 請求之中,而是把它放到 HTTP 頭中自定義的屬性裡。通過 XMLHttpRequest 這個類,可以一次性給所有該類請求加上 csrftoken 這個 HTTP 頭屬性,並把 token 值放入其中。這樣解決了上種方法在請求中加入 token 的不便,同時,通過 XMLHttpRequest 請求的地址不會被記錄到瀏覽器的位址列,也不用擔心 token 會透過 Referer 洩露到其他網站中去。
然而這種方法的侷限性非常大。XMLHttpRequest 請求通常用於 Ajax 方法中對於頁面區域性的非同步重新整理,並非所有的請求都適合用這個類來發起,而且通過該類請求得到的頁面不能被瀏覽器所記錄下,從而進行前進,後退,重新整理,收藏等操作,給使用者帶來不便。另外,對於沒有進行 CSRF 防護的遺留系統來說,要採用這種方法來進行防護,要把所有請求都改為 XMLHttpRequest 請求,這樣幾乎是要重寫整個網站,這代價無疑是不能接受的。
10.script標籤到defer和async屬性有什麼作用和區別
async屬性,表示後續文件的載入和渲染與js指令碼的載入和執行是並行進行的,即非同步執行。
defer屬性,載入後續文件的過程和js指令碼的載入(此時僅載入不執行)是並行進行的(非同步),js指令碼的執行需要等到文件所有元素解析完成之後,DOMContentLoaded事件觸發執行之前。
區別
1.defer和async在網路載入過程是一致的,都是非同步執行的;
2.兩者的區別在於指令碼載入完成之後何時執行,defer更符合大多數場景對應用指令碼載入和執行的要求;
3.如果存在多個有defer屬性的指令碼,那麼它們是按照載入順序執行指令碼的;而對於async,它的載入和執行是緊緊挨著的,無論宣告順序如何,只要載入完成就立刻執行,它對於應用指令碼用處不大,因為它完全不考慮依賴。