菜鸡前端面试题整理日记
一直以來都有寫點(diǎn)什么東西的想法,但又整天猶猶豫豫的,一會覺得準(zhǔn)備不夠充分,寫的內(nèi)容沒什么質(zhì)量,一會又覺得沒什么內(nèi)容可寫的,以至于一拖再拖。萬事開頭難,難著難著就沒有下面了,以此先開個頭,記錄自己的成長歷程也是不錯的,或許順便還能幫上一些人呢。
分享個剛踏出校門的菜鳥所整理的前端面試題,當(dāng)初被問到一時答不出來的問題,不會很詳細(xì)和深入,對面試還是有點(diǎn)用的,僅供參考。
索引
- 1.事件冒泡、事件捕獲
- 2.js的數(shù)據(jù)類型和判斷方法
- 3.js中的六種假值
- 4.js添加、刪除一個節(jié)點(diǎn)
- 5.js獲取日期(#l5)
- 6.正則
- 7.eval的用法
- 8.閉包
- 9.獲取元素最終CSS樣式的方法
- 10.普通函數(shù)和構(gòu)造函數(shù)的區(qū)別
- 11.瀏覽器的兼容
- 12.數(shù)組去重
- 13.sessionStorage 、localStorage 和 cookie 之間的區(qū)別
- 14.行內(nèi)元素有哪些?塊級元素有哪些? 空(void)元素有那些?
- 15.頁面導(dǎo)入樣式時,使用link和@import有什么區(qū)別?
- 16.對瀏覽器內(nèi)核的理解
- 17.常見的瀏覽器內(nèi)核有哪些?
- 18.HTML5新特性
- 19.如何處理HTML5新標(biāo)簽的瀏覽器兼容問題
- 20.簡述你對語義化的理解
- 21.Form表單中method=post/get兩種數(shù)據(jù)傳輸?shù)姆绞降膮^(qū)別
- 22.回調(diào)函數(shù)和普通函數(shù)的區(qū)別
- 23.web頁面性能優(yōu)化
- 24.JSON和JSONP的區(qū)別
- 25.call 和 apply 的區(qū)別
- 26.transform的屬性
- 27.css3的動畫
- 28.js不同瀏覽器兼容問題
- 29.ios-安卓兼容問題
- 30.es6(es2015)常用語法
1.事件冒泡、事件捕獲
1)冒泡型事件:事件從事件目標(biāo)開始,往上冒泡直到頁面的最上一級標(biāo)簽(document)。
2)捕獲型事件:事件從最上一級標(biāo)簽(document)開始往下查找,直到捕獲到事件目標(biāo)。
3)DOM事件流:同時支持兩種事件模型:捕獲型事件和冒泡型事件,但是,捕獲型事件先發(fā)生。兩種事件流會觸及DOM中的所有對象,從document對象開始,也在document對象結(jié)束。
W3C標(biāo)準(zhǔn)瀏覽器用addEventListener(event,fn,useCapture)方法添加事件;基中第3個參數(shù)useCapture是一個Boolean值,用來設(shè)置事件是在事件捕獲時執(zhí)行,還是事件冒泡(false)時執(zhí)行。
不兼容W3C的瀏覽器(IE)用attachEvent()方法,此方法沒有相關(guān)設(shè)置。
E的事件模型默認(rèn)是在事件冒泡時執(zhí)行的,也就是在useCapture等于false的時候執(zhí)行,所以把在處理事件時把useCapture設(shè)置為false是比較安全,也實(shí)現(xiàn)兼容瀏覽器的效果。
事件的傳播是可以阻止的:
在W3c中,使用stopPropagation()方法
在IE下設(shè)置cancelBubble = true;
2.js的數(shù)據(jù)類型和判斷方法
1)js中有5種數(shù)據(jù)類型:
Undefined 、 Null 、 Boolean 、 Number 和 String;
還有一種復(fù)雜的數(shù)據(jù)類型Object。
2)數(shù)據(jù)類型判斷
// typeof,判斷數(shù)組時是Object;// instanceof,判斷已知對象類型的方法 alert(c instanceof Array) // ---------------> trueObject.prototype.toString.call() alert(Object.prototype.toString.call(c) === ‘[object Array]’) //-------> true;3.js中的六種假值
false 、 null 、 undefined 、 0 、 '' (空字符串) 、 NaN;
除了這6個外,其它均為“真” ,包括對象、數(shù)組、正則、函數(shù)等。注意 '0'、'null'、'false'、{}、[]也都是真值。
4.js添加、刪除一個節(jié)點(diǎn)
<script> window.onload=function(){//----------------------添加節(jié)點(diǎn)var boxObj = document.getElementById("box");var newNode = document.createElement("h1");var txtNode = document.createTextNode("h1內(nèi)容");newNode.appendChild(txtNode);boxObj.appendChild(newNode);//----------------------刪除節(jié)點(diǎn)var oldNode = document.getElementsByTagName("p")[0];boxObj.removeChild(oldNode); } </script>5.js獲取日期
// 月份和星期需要加1。var t=new Date(); t.getFullYear()//年份 t.getMonth()//月份 t.getDate()//一個月的當(dāng)天 t.getDay()//星期 t.getHours()//小時 t.getMinutes()//分鐘 t.getSecounds()//秒 t.getTime()//返回1970年1月1日至今的毫秒數(shù) t.parse("2017/1/1/ 00:00:00")//返回1970年1月1日到指定日期的毫秒數(shù) t.toLocaleString()//完整日期時間6.正則
// /^[ab]{2,6}$/i // 方括號是只能在ab中選一個; // 大括號是只能出現(xiàn)2-6次; // i是忽略大小寫。// \d任意數(shù)字; // \D非數(shù)字; // \w[A-Z a-z _ 0-9];7.eval的用法?
1)eval() 函數(shù)可計算某個字符串,并執(zhí)行其中的的 JavaScript 代碼。
2)該方法只接受原始字符串作為參數(shù),如果 string 參數(shù)不是原始字符串,那么該方法將不作任何改變地返回。因此請不要為 eval() 函數(shù)傳遞 String 對象來作為參數(shù)。
8.閉包
一、閉包(closure)是Javascript語言的一個難點(diǎn),也是它的特色,很多高級應(yīng)用都要依靠閉包實(shí)現(xiàn)。
閉包有三個特性:
1.函數(shù)嵌套函數(shù)
2.函數(shù)內(nèi)部可以引用外部父函數(shù)的參數(shù)和變量
3.參數(shù)和變量不會被垃圾回收機(jī)制回收
二、閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù),創(chuàng)建閉包的最常見的方式就是在A函數(shù)內(nèi)創(chuàng)建B函數(shù),通過B函數(shù)訪問A函數(shù)的局部變量
三、使用閉包有一個優(yōu)點(diǎn),也是它的缺點(diǎn),就是可以把局部變量駐留在內(nèi)存中,可以避免使用全局變量。全局變量在每個模塊都可調(diào)用,這勢必將是災(zāi)難性的。
所以推薦使用私有的,封裝的局部變量。
四、一般函數(shù)執(zhí)行完畢后,局部活動對象就被銷毀,,內(nèi)存中僅僅保存全局作用域。但閉包的情況不同!
五、那么使用閉包有什么好處呢?使用閉包的好處是:
1.希望一個變量長期駐扎在內(nèi)存中
2.避免全局變量的污染
3.私有成員的存在
9.獲取元素最終CSS樣式的方法:
1、obj.style.attr :獲取內(nèi)部樣式。 (attr代表CSS樣式屬性)
2、obj.currentStyle[attr] : 兼容IE,獲取元素最終樣式(內(nèi)部、外部樣式最后的效果),只讀
3、window.getComputedStyle(obj , null)[attr]; 兼容FF,chrome,safiri,只讀
// 測試兼容性alert(cont.currentStyle); //在谷歌中輸出“undefined”,在IE中輸出“[object CSSCurrentStyleDeclaration]”;// 示例var cont=document.getElementById("cont");// alert(cont.currentStyle);if (cont.currentStyle){alert("height:"+cont.currentStyle["height"]);}else{alert("height:"+getComputedStyle(cont,null)["height"]}10.普通函數(shù)和構(gòu)造函數(shù)的區(qū)別 :
普通函數(shù)與構(gòu)造函數(shù)相比有四個明顯特點(diǎn):
1.不需要用new關(guān)鍵字調(diào)用
2.可以用return語句返回值
3.函數(shù)內(nèi)部不建議使用this關(guān)鍵字
4.函數(shù)命名以駝峰方式,首字母小寫
11.瀏覽器的兼容
1)margin加倍的問題
設(shè)置為float的div在ie下設(shè)置的margin會加倍。這是一個ie6都存在的bug。解決方案是在這個div里面加上display:inline;
2)文本在Div的垂直居中問題
vertical-align:middle; 將行距增加到和整個DIV一樣高:line-height:200px; 然后插入文字,就垂直居中了。缺點(diǎn)是要控制內(nèi)容不要換行。
12.數(shù)組去重
//第一種 刪除后面重復(fù)元素function removeRepeat1(a){for(var i=0;i<a.length;i++){for(var j=i+1;j<a.length;j++){if(a[i]===a[j]){a.splice(j,1);j--; //否則若是多個一樣的數(shù)字連在一起則只能去掉一個}}} return a.sort(function(a,b){return a-b}); } console.log(removeRepeat1(arr));//第二種 相互比較元素,碰到相同的則跳出循環(huán)function removeRepeat(a) {var b = [], n = a.length;for (var i = 0; i < n; i++){for (var j = i+1; j < n; j++){if (arr[i] === arr[j]){j=false;break;}}if(j){b.push(a[i]);}}return b.sort(function(a,b){return a-b}); }console.log(removeRepeat(arr));13.sessionStorage 、localStorage 和 cookie 之間的區(qū)別
共同點(diǎn):
都是保存在瀏覽器端,且同源的。
區(qū)別:
1)cookie數(shù)據(jù)始終在同源的http請求中攜帶(即使不需要),即cookie在瀏覽器和服務(wù)器間來回傳遞。而sessionStorage和localStorage不會自動把數(shù)據(jù)發(fā)給服務(wù)器,僅在本地保存。
2)存儲大小限制也不同,cookie數(shù)據(jù)不能超過4k,同時因?yàn)槊看蝖ttp請求都會攜帶cookie,所以cookie只適合保存很小的數(shù)據(jù),如會話標(biāo)識。sessionStorage和localStorage 雖然也有存儲大小的限制,但比cookie大得多,可以達(dá)到5M或更大。
3)數(shù)據(jù)有效期不同,sessionStorage:僅在當(dāng)前瀏覽器窗口關(guān)閉前有效,自然也就不可能持久保持;localStorage:始終有效,窗口或?yàn)g覽器關(guān)閉也一直保存,因此用作持久數(shù)據(jù);cookie只在設(shè)置的cookie過期時間之前一直有效,即使窗口或?yàn)g覽器關(guān)閉。
4)作用域不同,sessionStorage不在不同的瀏覽器窗口中共享,即使是同一個頁面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。
14.行內(nèi)元素有哪些?塊級元素有哪些? 空(void)元素有那些?
(1)行內(nèi)元素有:a b span img input select strong(強(qiáng)調(diào)的語氣)
(2)塊級元素有:div ul ol li dl dt dd h1 h2 h3 h4…p
(3)常見的空元素(沒有內(nèi)容的HTML內(nèi)容被稱為空元素):
<br> <hr> <img> <input> <link> <meta>15.頁面導(dǎo)入樣式時,使用link和@import有什么區(qū)別?
(1)link屬于XHTML標(biāo)簽,除了加載CSS外,還能用于定義RSS, 定義rel連接屬性等作用;而@import是CSS提供的,只能用于加載CSS;
(2)頁面被加載的時,link會同時被加載,而@import引用的CSS會等到頁面被加載完再加載;
(3)import是CSS2.1 提出的,只在IE5以上才能被識別,而link是XHTML標(biāo)簽,無兼容問題;
16.對瀏覽器內(nèi)核的理解
主要分成兩部分:
渲染引擎(layout engineer或Rendering Engine)和JS引擎。
渲染引擎:
負(fù)責(zé)取得網(wǎng)頁的內(nèi)容(HTML、XML、圖像等等)、整理訊息(例如加入CSS等),以及計算網(wǎng)頁的顯示方式,然后會輸出至顯示器或打印機(jī)。瀏覽器的內(nèi)核的不同對于網(wǎng)頁的語法解釋會有不同,所以渲染的效果也不相同。所有網(wǎng)頁瀏覽器、電子郵件客戶端以及其它需要編輯、顯示網(wǎng)絡(luò)內(nèi)容的應(yīng)用程序都需要內(nèi)核。
JS引擎則:
解析和執(zhí)行javascript來實(shí)現(xiàn)網(wǎng)頁的動態(tài)效果。
最開始渲染引擎和JS引擎并沒有區(qū)分的很明確,后來JS引擎越來越獨(dú)立,內(nèi)核就傾向于只指渲染引擎。
17.常見的瀏覽器內(nèi)核有哪些?
Trident內(nèi)核:IE,MaxThon,TT,The World,360,搜狗瀏覽器等。[又稱MSHTML]
Gecko內(nèi)核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey等
Presto內(nèi)核:Opera7及以上。 [Opera內(nèi)核原為:Presto,現(xiàn)為:Blink;]
Webkit內(nèi)核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]
18.HTML5新特性
主要是關(guān)于圖像,位置,存儲,多任務(wù)等功能的增加。
1 繪畫 canvas;
2 用于媒介回放的 video 和 audio 元素;
3 本地離線存儲 localStorage 長期存儲數(shù)據(jù),瀏覽器關(guān)閉后數(shù)據(jù)不丟失;
4 sessionStorage 的數(shù)據(jù)在瀏覽器關(guān)閉后自動刪除;
5 語意化更好的內(nèi)容元素,比如 article、footer、header、nav、section;
6 表單控件,calendar、date、time、email、url、search;
7 新的技術(shù)webworker, websockt, Geolocation;
19.如何處理HTML5新標(biāo)簽的瀏覽器兼容問題
IE8/IE7/IE6支持通過document.createElement方法產(chǎn)生的標(biāo)簽,
可以利用這一特性讓這些瀏覽器支持HTML5新標(biāo)簽,
瀏覽器支持新標(biāo)簽后,還需要添加標(biāo)簽?zāi)J(rèn)的樣式。
當(dāng)然最好的方式是直接使用成熟的框架、使用最多的是html5shim框架
<!--[if lt IE 9]> <script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script> <![endif]-->20.簡述你對語義化的理解
讓頁面的內(nèi)容結(jié)構(gòu)化,結(jié)構(gòu)更清晰,便于瀏覽器、搜索引擎解析;
便于看代碼的人將網(wǎng)站分塊,能更好的讀代碼和維護(hù)。
21.Form表單中method=post/get兩種數(shù)據(jù)傳輸?shù)姆绞降膮^(qū)別
一、Form提供了兩種數(shù)據(jù)傳輸?shù)姆绞健猤et和post, get是默認(rèn)方法;
二、傳輸方式不同:
(1)Get 方法通過 URL 請求來傳遞用戶的數(shù)據(jù),將表單內(nèi)各字段名稱與其內(nèi)容,以成對的字符串連接,置于 action 屬性所指程序的 url 后,如http://www.mdm.com/test.asp?name=asd&password=sad,數(shù)據(jù)都會直接顯示在 url 上,就像用戶點(diǎn)擊一個鏈接一樣;
(2)Post是將表單中的數(shù)據(jù)放在form的數(shù)據(jù)體中,按照變量和值相對應(yīng)的方式,傳遞到action所指向URL。?
三、安全性不同:
(1)Get是不安全的,因?yàn)樵趥鬏斶^程,數(shù)據(jù)被放在請求的URL中,而如今現(xiàn)有的很多服務(wù)器、代理服務(wù)器或者用戶代理都會將請求URL記錄到日志文件中,然后放在某個地方,這樣就可能會有一些隱私的信息被第三方看到。另外,用戶也可以在瀏覽器上直接看到提交的數(shù)據(jù),一些系統(tǒng)內(nèi)部消息將會一同顯示在用戶面前。
(2)Post的所有操作對用戶來說都是不可見的。?
四、傳輸數(shù)據(jù)長度不同:
(1)Get傳輸?shù)臄?shù)據(jù)量小,這主要是因?yàn)槭躑RL長度限制;
(2)而Post可以傳輸大量的數(shù)據(jù),所以在上傳文件只能使用Post
五、支持的字符集不同:
(1)Get限制Form表單的數(shù)據(jù)集的值必須為ASCII字符
(2)而Post支持整個ISO10646字符集。
22.回調(diào)函數(shù)和普通函數(shù)的區(qū)別
普通函數(shù),被其他函數(shù)調(diào)用時,是在調(diào)用者內(nèi)部直接寫函數(shù)名調(diào)
回調(diào)函數(shù),通常是作為參數(shù)傳遞給調(diào)用者,調(diào)用者并不知道自己調(diào)用的到底是什么
另外有一點(diǎn),回調(diào)函數(shù)大多用于多線程的情況
23.web頁面性能優(yōu)化
一、減少HTTP請求:
這個是由于瀏覽器對同一個host有并行下載的限制,http請求越多,總體下載速度越慢
(1)使用CSS Sprites
(2)合并JS和CSS文件
二、CSS、JS方面:
1) 一般情況下建議css和js采用外聯(lián)式。
2)將CSS放在頂部:?能加快頁面內(nèi)容顯示,并且能避免頁面產(chǎn)生白屏
3)將JS放在底部 : JS會阻塞對其后面內(nèi)容的呈現(xiàn)
4) 精簡JS和CSS文件 :減少重復(fù)性代碼,代碼重復(fù)利用,在這里顯得特別重要。要把你的css規(guī)劃好,盡量的采用縮寫,這樣可以減少css文件的大小,那么對css做相應(yīng)的規(guī)劃也可以減少css的個數(shù),減少http請求數(shù),js同理。
5)移除重復(fù)的腳本
三、背景圖片數(shù)量及大小的優(yōu)化
1)內(nèi)容圖片要優(yōu)化,減少文件大小。
2)背景圖片:
(1)圖片精靈 css sprite ,減少圖片數(shù)量,減少HTTP請求。
(2)png8的格式會相對比gif小
四、可以模仿淘寶,使用CDN,圖片,jS,css互相之間都使用了不同的域名.單是圖片服務(wù)器,下面又使用了很多不同的服務(wù)器,比如img01.taobaocdn.com等等
24.JSON和JSONP的區(qū)別
1)JSON:是一種輕量級的數(shù)據(jù)交換格式,可以在瀏覽器和服務(wù)器之間交換信息。
2)JSONP(JSON With Padding),就是打包在函數(shù)調(diào)用中的的JSON(或者包裹的JSON),用來實(shí)現(xiàn)跨域請求。
3)JSON是一種數(shù)據(jù)格式,JSONP是一種數(shù)據(jù)調(diào)用方式。
25.call 和 apply 的區(qū)別
1)在js中call和apply它們的作用都是將函數(shù)綁定到另外一個對象上去運(yùn)行,兩者僅在定義參數(shù)方式有所區(qū)別
2) apply和call的用法只有一個地方不一樣,除此之外,其他地方基本一模一樣
a.call(b,arg1,arg2…)apply(b,[arg1,arg2]) //apply只有2個參數(shù),它將call的參數(shù)(arg1,arg2…)放在一個數(shù)組中作為apply的第二參數(shù)26.transform的屬性
rotate(0deg)順時針旋轉(zhuǎn)0度
skew(x,y)變形,不旋轉(zhuǎn) skewX(deg) skewY(deg)
scale(x,y)縮放
translate(x,y)位移
transf-origin 改變原點(diǎn):
top(50%,0) right(100%,50%)
bottom(50%,100%) left(0,,50%)
27.css3的動畫
transition-property:all所有要運(yùn)動的屬性名
-duration:2s 過渡時間
-timing-function:ease/linear指定過度函數(shù)
-delay:延遲時間
關(guān)鍵幀
@Keyframes a{
0%{}
100%{}}
animation:a 2s;(a為上面的函數(shù)名)
animation-iteration-count:infinite(無限循環(huán))循環(huán)次數(shù)
28.js不同瀏覽器兼容問題
七、input.type屬性問題
問題說明:IE下 input.type 屬性為只讀;但是Firefox下 input.type 屬性為讀寫。
解決辦法:不修改 input.type 屬性。如果必須要修改,可以先隱藏原來的input,然后在同樣的位置再插入一個新的input元素。
八、window.event問題
問題說明:window.event 只能在IE下運(yùn)行,而不能在Firefox下運(yùn)行,這是因?yàn)镕irefox的event只能在事件發(fā)生的現(xiàn)場使用。
解決方法:在事件發(fā)生的函數(shù)上加上event參數(shù),在函數(shù)體內(nèi)(假設(shè)形參為evt)使用 var myEvent = evt?evt:(window.event?window.event:null)
示例:
九、event.x與event.y問題
問題說明:IE下,even對象有x、y屬性,但是沒有pageX、pageY屬性;Firefox下,even對象有pageX、pageY屬性,但是沒有x、y屬性。
解決方法:var myX = event.x ? event.x : event.pageX; var myY = event.y ? event.y:event.pageY;
如果考慮第8條問題,就改用myEvent代替event即可。
十七、innerText的問題.
問題說明:innerText在IE中能正常工作,但是innerText在FireFox中卻不行。
解決方法:在非IE瀏覽器中使用textContent代替innerText。
29.ios-安卓兼容問題
1)虛擬鍵盤引起的兼容問題。
ios虛擬鍵盤懸浮到瀏覽器上,蓋住輸入框;安卓會把瀏覽器窗口頂起,瀏覽器高度變小
2)上下拉動滾動條時卡頓、慢
body {-webkit-overflow-scrolling:
touch; overflow-scrolling: touch;}
Android3+和iOS5+支持CSS3的新屬性為overflow-scrolling
3)iphone及ipad下輸入框默認(rèn)內(nèi)陰影
Element{
-webkit-appearance:none;
}
4)active兼容處理 即 偽類 :active 失效
// 方法一:body添加ontouchstart <body ontouchstart="">// 方法二:js給 document 綁定 touchstart 或 touchend 事件 <style> a {color:#000; } a:active {color:#fff; } </style> <a herf=foo >bar</a> <script>document.addEventListener('touchstart',function(){},false); </script>30.es6(es2015)常用語法
1)變量聲明const和let
let表示變量、const表示常量。let和const都是塊級作用域。( {}大括號內(nèi)的代碼塊即為let 和 const的作用域。)
2)函數(shù)默認(rèn)參數(shù)
function action(num = 200) {console.log(num) } action(0) // 0 action() //200 action(300) //3003)箭頭函數(shù)
不需要 function 關(guān)鍵字來創(chuàng)建函數(shù)
省略 return 關(guān)鍵字
繼承當(dāng)前上下文的 this 關(guān)鍵字
ps:當(dāng)你的函數(shù)有且僅有一個參數(shù)的時候,是可以省略掉括號的。當(dāng)你函數(shù)返回有且僅有一個表達(dá)式的時候可以省略{} 和 return
4)對象簡寫
ES6通過省略冒號與 function 關(guān)鍵字,將這個語法變得更簡潔
`const people = { name: 'lux', getName () { console.log(this.name) } }
5)解構(gòu)
// ES5我們提取對象中的信息形式如下:const people = {name: 'lux',age: 20 } const name = people.name const age = people.age console.log(name + ' --- ' + age)// 在ES6,解構(gòu)能讓我們從對象或者數(shù)組里取出數(shù)據(jù)存為變量://對象const people = {name: 'lux',age: 20 } const { name, age } = people console.log(`${name} --- ${age}`) //數(shù)組 const color = ['red', 'blue'] const [first, second] = color console.log(first) //'red' console.log(second) //'blue'6)展開運(yùn)算符(...)
組裝對象或者數(shù)組
7) Promise
說白了就是用同步的方式去寫異步代碼。
面試題:
setTimeout(function() {console.log(1)}, 0);new Promise(function executor(resolve) {console.log(2);for( var i=0 ; i<10000 ; i++ ) {i == 9999 && resolve();}console.log(3);}).then(function() {console.log(4);});console.log(5); // 順序:2 3 5 4 undefined(resolve()) 1轉(zhuǎn)載于:https://www.cnblogs.com/xiangzhaode/p/10646176.html
總結(jié)
以上是生活随笔為你收集整理的菜鸡前端面试题整理日记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CODEFORCES 272C Di
- 下一篇: Nginx配置浏览器缓存