最近試著提升自己的前端技術(shù),發(fā)現(xiàn)其實從面試題去學(xué)習(xí)和吸收知識也是非常不錯的選擇!不僅能快速的抓住知識點,而且還能應(yīng)對以后的面試。簡直是一舉兩得(哈哈哈哈)。
目前只從三元大神那里獲取的面試內(nèi)容(有興趣可以看一下):
阿里云前端實習(xí)生面試 | 三元博客
=。= 目前還沒更新完(哭唧唧)
瀏覽器緩存機制
一,瀏覽器緩存類型
- 強緩存:不會向服務(wù)器發(fā)送請求,直接從緩存中讀取資源,在chrome控制臺的network選項中可以看到該請求返回200的狀態(tài)碼,并且size顯示from disk cache或from memory cache;
- 協(xié)商緩存:向服務(wù)器發(fā)送請求,服務(wù)器會根據(jù)這個請求的request header的一些參數(shù)來判斷是否命中協(xié)商緩存,如果命中,測返回304狀態(tài)碼并帶上新的response header通知瀏覽器從緩存中讀取資源;
兩者的共同點是,都是從客戶端緩存中讀取資源;區(qū)別是強緩存不會發(fā)請求,協(xié)商緩存會發(fā)請求。
二、緩存有關(guān)的header
強緩存
Expires:response header里的過期時間,瀏覽器再次加載資源時,如果在這個過期時間內(nèi),則命中強緩存。
Cache-Control:當(dāng)值設(shè)為max-age=300時,則代表在這個請求正確返回時間(瀏覽器也會記錄下來)的5分鐘內(nèi)再次加載資源,就會命中強緩存。
Expires和Cache-Control:max-age=*** 的作用是差不多的,區(qū)別就在于 Expires 是http1.0的產(chǎn)物,Cache-Control是http1.1的產(chǎn)物,兩者同時存在的話,Cache-Control優(yōu)先級高于Expires;在某些不支持HTTP1.1的環(huán)境下,Expires就會發(fā)揮用處。所以Expires其實是過時的產(chǎn)物,現(xiàn)階段它的存在只是一種兼容性的寫法
(編輯補充:Expires和Cache-Control的區(qū)別還有一個:Expires是一個具體的服務(wù)器時間,這就導(dǎo)致一個問題,如果客戶端時間和服務(wù)器時間相差較大,緩存命中與否就不是開發(fā)者所期望的。Cache-Control是一個時間段,控制就比較容易。)
協(xié)商緩存
ETag和If-None-Match:這兩個要一起說。Etag是上一次加載資源時,服務(wù)器返回的response header,是對該資源的一種唯一標(biāo)識,只要資源有變化,Etag就會重新生成。瀏覽器在下一次加載資源向服務(wù)器發(fā)送請求時,會將上一次返回的Etag值放到request header里的If-None-Match里,服務(wù)器接受到If-None-Match的值后,會拿來跟該資源文件的Etag值做比較,如果相同,則表示資源文件沒有發(fā)生改變,命中協(xié)商緩存
Last-Modified和If-Modified-Since:這兩個也要一起說。Last-Modified是該資源文件最后一次更改時間,服務(wù)器會在response header里返回,同時瀏覽器會將這個值保存起來,在下一次發(fā)送請求時,放到request header里的If-Modified-Since里,服務(wù)器在接收到后也會做比對,如果相同則命中協(xié)商緩存。
ETag和Last-Modified的作用和用法也是差不多,說一說他們的區(qū)別。
首先在精確度上,Etag要優(yōu)于Last-Modified。Last-Modified的時間單位是秒,如果某個文件在1秒內(nèi)改變了多次,那么他們的Last-Modified其實并沒有體現(xiàn)出來修改,但是Etag每次都會改變確保了精度;如果是負載均衡的服務(wù)器,各個服務(wù)器生成的Last-Modified也有可能不一致。
第二在性能上,Etag要遜于Last-Modified,畢竟Last-Modified只需要記錄時間,而Etag需要服務(wù)器通過算法來計算出一個hash值。
第三在優(yōu)先級上,服務(wù)器校驗優(yōu)先考慮Etag。
三、瀏覽器緩存過程
- 瀏覽器第一次加載資源,服務(wù)器返回200,瀏覽器將資源文件從服務(wù)器上請求下載下來,并把response header及該請求的返回時間一并緩存;
- 下一次加載資源時,先比較當(dāng)前時間和上一次返回200時的時間差,如果沒有超過cache-control設(shè)置的max-age,則沒有過期,命中強緩存,不發(fā)請求直接從本地緩存讀取該文件(如果瀏覽器不支持HTTP1.1,則用expires判斷是否過期);如果時間過期,則向服務(wù)器發(fā)送header帶有If-None-Match和If-Modified-Since的請求;
- 服務(wù)器收到請求后,優(yōu)先根據(jù)Etag的值判斷被請求的文件有沒有做修改,Etag值一致則沒有修改,命中協(xié)商緩存,返回304;如果不一致則有改動,直接返回新的資源文件帶上新的Etag值并返回200;
- 如果服務(wù)器收到的請求沒有Etag值,則將If-Modified-Since和被請求文件的最后修改時間做比對,一致則命中協(xié)商緩存,返回304;不一致則返回新的last-modified和文件并返回200;
三、用戶行為對瀏覽器緩存的控制
- 地址欄訪問,鏈接跳轉(zhuǎn)是正常用戶行為,將會觸發(fā)瀏覽器緩存機制;
- F5刷新,瀏覽器會設(shè)置max-age=0,跳過強緩存判斷,會進行協(xié)商緩存判斷;
- ctrl+F5刷新,跳過強緩存和協(xié)商緩存,直接從服務(wù)器拉取資源。
四、實際應(yīng)用
當(dāng)在實際應(yīng)用中時,對于所有可緩存資源,一般需要指定一個 Expires 或 Cache-Control max-age以及一個Last-Modified或ETag。這樣既能控制強緩存,也能控制協(xié)商緩存。但是由于 Cache-Control 只支持 http 1.1,如果需要兼容老設(shè)備,還是需要 Expires,它既支持 http1.0 也支持 http 1.1。
但是如果對于一個不是經(jīng)常改變的靜態(tài)資源來說,我們可以通過服務(wù)器來告訴瀏覽器是否需要重新請求,這樣就避免了很多 304。
比如我們可以通過在 url 后面加上 md5 參數(shù)或者將 md5 參數(shù)寫成文件名的一部分來實現(xiàn)。
當(dāng)資源沒有變動的時候直接使用緩存,不用發(fā)起請求,當(dāng)資源發(fā)生變化時,其 url 就會發(fā)生變化。網(wǎng)址一經(jīng)更改,系統(tǒng)就會強制瀏覽器重新抓取資源。
https://www.cnblogs.com/vajoy/p/5341664.html
cookie屬性詳解
-
name: 字段為一個cookie的名稱 -
value: 字段為一個cookie的值 -
domain: 字段為可以訪問此cookie的域名 -
path: 字段為可以訪問此cookie的頁面路徑。 比如domain是abc.com,path是/test,那么只有/test路徑下的頁面可以讀取此cookie。 -
expires/Max-Age:字段為此cookie超時時間。若設(shè)置其值為一個時間,那么當(dāng)?shù)竭_此時間后,此cookie失效。不設(shè)置的話默認(rèn)值是Session,意思是cookie會和session一起失效。當(dāng)瀏覽器關(guān)閉(不是瀏覽器標(biāo)簽頁,而是整個瀏覽器) 后,此cookie失效。 -
Size:字段 此cookie大小 -
http:字段 cookie的httponly屬性。若此屬性為true,則只有在http請求頭中會帶有此cookie的信息,而不能通過document.cookie來訪問此cookie。 -
secure字段 設(shè)置是否只能通過https來傳遞此條cookie -
Session意思是cookie會和session一起失效。當(dāng)瀏覽器關(guān)閉(不是瀏覽器標(biāo)簽頁,而是整個瀏覽器) 后,此cookie失效。
箭頭函數(shù)和普通函數(shù)的區(qū)別
箭頭函數(shù)不綁定this,會捕獲其所在的上下文的this值,作為自己的this值
var obj = {
a: 10,
b: () => {
console.log(this.a); // undefined
console.log(this); // Window {postMessage: ?, blur: ?, focus: ?, close: ?, frames: Window, …}
},
c: function() {
console.log(this.a); // 10
console.log(this); // {a: 10, b: ?, c: ?}
}
}
obj.b();
obj.c();
箭頭函數(shù)不綁定arguments,取而代之用rest參數(shù)...解決
function A(a){ console.log(arguments)}
A(2,'sdas','asda')
Arguments(3) [2, "sdas", "asda", callee: ?, Symbol(Symbol.iterator): ?]
let B = (b)=>{
console.log(arguments);
}
B(2,92,32,32); // Uncaught ReferenceError: arguments is not defined
let C = (...c) => {
console.log(c);
}
C(3,82,32,11323); // [3, 82, 32, 11323]
箭頭函數(shù)是匿名函數(shù)不能作為構(gòu)造函數(shù)使用,不能使用new
let a = () => { console.log(111)}
a()
let fn = new a()
VM325:1 Uncaught TypeError: a is not a constructor
at <anonymous>:1:10
箭頭函數(shù)沒有原型屬性
var a = ()=>{
return 1;
}
function b(){
return 2;
}
console.log(a.prototype); // undefined
console.log(b.prototype); // {constructor: ?}
箭頭函數(shù)不能當(dāng)做Generator函數(shù),不能使用yield關(guān)鍵字
// 普通函數(shù)的this指向調(diào)用他的對象
// 箭頭函數(shù)的this指向調(diào)用父級的對象,如果父級作用于還是箭頭函數(shù),就繼續(xù)向上找,直到window
(補充)箭頭函數(shù)體內(nèi)的this對象,就是 定義時所在的對象,而不是使用時所在的對象。而普通函數(shù)中this指向是可變的,普通函數(shù)的this指向調(diào)用它的那個對象