原來(lái)是8月29號(hào)早上接到的一個(gè)深圳的電話,還以為是什么廣告電話,一說(shuō)是騰訊的馬上一個(gè)激靈站起來(lái),什么準(zhǔn)備都沒(méi)有,跟面試官說(shuō)現(xiàn)在沒(méi)空,然后約了晚上7點(diǎn)再面試,到晚上7點(diǎn)面試官說(shuō)臨時(shí)有會(huì)議改到9點(diǎn)再面,到九點(diǎn)多還沒(méi)打電話過(guò)來(lái),短信過(guò)去詢問(wèn),說(shuō)會(huì)議剛結(jié)束,改約了30號(hào)早上(也是辛苦啊,開(kāi)到9點(diǎn)多)。
言歸正傳,第一次接到春招電面,之前看了別人的面經(jīng),其實(shí)問(wèn)到的問(wèn)題其他人的面經(jīng)都有說(shuō)到,遺憾沒(méi)有深入去理解,只是看了個(gè)皮毛!而且對(duì)一些必問(wèn)題也沒(méi)有準(zhǔn)備得很好!
下面是面試題:
1. 說(shuō)說(shuō)在學(xué)習(xí)的過(guò)程中遇到什么問(wèn)題,怎么解決的
說(shuō)了我學(xué)框架學(xué)相關(guān)知識(shí)遇到問(wèn)題都是通過(guò)谷歌解決,面試官讓說(shuō)具體的例子,想了好久,面試官也很有耐心在等,最后說(shuō)我太緊張了現(xiàn)在想不起來(lái)。
2.說(shuō)說(shuō)JS的作用域
說(shuō)了JS沒(méi)有塊級(jí)作用域,ES6之后才有,作用域嵌套,當(dāng)嵌套作用域內(nèi)找不到變量會(huì)一直往上找,直到全局作用域。
面試官追問(wèn)嵌套的作用域是不是一定能拿到外部作用域的變量,我說(shuō)可以,面試官舉了例子:如果嵌套作用域的變量跟嵌套作用域的變量相同呢?那當(dāng)然就獲取不到外部作用域的變量了...
后來(lái)好像聊到如果找不到變量會(huì)怎么辦,口誤說(shuō)了undefined,后來(lái)說(shuō)是會(huì)報(bào)錯(cuò),面試官說(shuō)報(bào)什么錯(cuò),我說(shuō) Uncaught,完整的報(bào)錯(cuò)忘記了,后來(lái)面試官說(shuō)是ReferenceError,后來(lái)發(fā)現(xiàn)完整的報(bào)錯(cuò)就是Uncaught ReferenceError,也可能是我表述的不清楚。
然后又問(wèn)了什么時(shí)候會(huì)報(bào) TypeError,答當(dāng)對(duì)一個(gè)非函數(shù)變量做函數(shù)調(diào)用會(huì)報(bào)TypeError
3.問(wèn)是不是學(xué)過(guò)React
說(shuō)是,跟面試官說(shuō)只是在開(kāi)始實(shí)習(xí)的時(shí)候才接觸React,面試官說(shuō)那說(shuō)說(shuō)React的聲明周期吧,說(shuō)了第一次渲染的生命周期,還有Props和State發(fā)生改變時(shí)的生命周期,還有卸載的生命周期。
問(wèn)有沒(méi)有用過(guò)Redux,說(shuō)只是做了簡(jiǎn)單的了解,跟他扯了一下Flux的dispatch - action - store...
4.問(wèn)知不知道緩存方面的東西
之前刷過(guò)面經(jīng)知道會(huì)問(wèn),一開(kāi)始就說(shuō)了HTTP緩存,看他的目的應(yīng)該是想讓我說(shuō)出瀏覽器緩存,說(shuō)了HTTP緩存好像覺(jué)得不錯(cuò),但是抓住HTTP緩存問(wèn)深了就被問(wèn)倒了...
說(shuō)了HTTP緩存分強(qiáng)制緩存和協(xié)商緩存
強(qiáng)制緩存有catch-control和 Expires,如果瀏覽器有強(qiáng)制緩存則請(qǐng)求不會(huì)到達(dá)服務(wù)器,直接使用強(qiáng)制緩存, Expires是HTTP1.0的請(qǐng)求頭,catch-control是HTTP1.1的請(qǐng)求頭,會(huì)優(yōu)先判斷catch-control。后面又問(wèn)了catch-control的max-age是干什么的。
然后又提了個(gè)問(wèn)題:為什么有了Expires又要多一個(gè)catch-control呢?再次被問(wèn)倒,這確實(shí)是個(gè)值得思考的問(wèn)題。
做了搜索,大致原因如下:
Expires返回的是一個(gè)絕對(duì)時(shí)間,如果客戶端和服務(wù)端的時(shí)間相差較大,比如修改了客戶端時(shí)間,緩存可能就會(huì)被過(guò)期用不了了。而cache-control使用的是一個(gè)相對(duì)時(shí)間max-age=多少秒,且做比較都是用客戶端時(shí)間做比較,可靠性比Expires更高。
回到面試,又說(shuō)了協(xié)商緩存,Etag和last-modified,如果沒(méi)命中強(qiáng)制緩存就會(huì)走協(xié)商緩存,請(qǐng)求會(huì)被發(fā)到服務(wù)器,判斷緩存是否過(guò)期,協(xié)商緩存面試官?zèng)]有繼續(xù)追問(wèn)。
后面又問(wèn)了知不知道 瀏覽器緩存 ,我不確定他說(shuō)的是不是 cookie、localStorage、sessionStorage這些瀏覽器存儲(chǔ),跟他說(shuō)可能我知道這方面的知識(shí)點(diǎn),但是不確定是不是你說(shuō)的,他說(shuō)了cookie,就知道了是這方面的東西。
跟他說(shuō)了cookie大小只有4kb,后面聊到可以用Iframe突破cookie的大小限制,然后就是cookie可以發(fā)送到服務(wù)器,用來(lái)實(shí)現(xiàn)記住登錄態(tài),購(gòu)物車(chē)功能。
繼續(xù)說(shuō)了localStorage,localStorage不會(huì)自動(dòng)刪除要手動(dòng)刪除,問(wèn)localStorage有沒(méi)有大小限制,似乎有接觸到這個(gè)問(wèn)題但是沒(méi)有留意,再次被問(wèn)倒...
做了搜索,顯然儲(chǔ)存毫無(wú)疑問(wèn)一定會(huì)有大小限制的,但是當(dāng)時(shí)好像回答的是沒(méi)有T T,localStorage的大小限制每個(gè)瀏覽器都是不同的,一般都限制在5 - 10M之間。
在面試的過(guò)程中面試官除了提問(wèn),如果你不懂還會(huì)跟你說(shuō)這方面的知識(shí),非常nice,他說(shuō)localStorage現(xiàn)在使用非常普遍,比如可以用來(lái)做首屏預(yù)加載,這個(gè)真的沒(méi)有好好了解過(guò),感覺(jué)針對(duì)瀏覽器緩存可以好好了解一下,寫(xiě)一篇文章。cookie的使用場(chǎng)景也是非常多,比如后面聊到的登錄驗(yàn)證,防范網(wǎng)絡(luò)攻擊。
5.有沒(méi)有了解XSS和CSRF
這個(gè)真的很可惜啊,聊到XSS的時(shí)候沒(méi)答出來(lái)具體的XSS手段和防范措施,這個(gè)在別人的面經(jīng)有看到過(guò)會(huì)問(wèn)這個(gè)問(wèn)題,但是沒(méi)有仔細(xì)鉆研,大概是回答的最差的一道了。
面試官先問(wèn)了CSRF,跨站點(diǎn)請(qǐng)求偽造,舉了一個(gè)惡意郵件打開(kāi)轉(zhuǎn)賬頁(yè)面的例子,面試官繼續(xù)追問(wèn)有什么方法可以預(yù)防CSRF,說(shuō)了可以通過(guò)在請(qǐng)求頭的Referer字段做檢查,這個(gè)是之前在維基上看到的,因?yàn)镽eferer字段的作用就是可以知道用戶是從哪個(gè)域名跳轉(zhuǎn)到上面提到的轉(zhuǎn)賬頁(yè)面的,以此判斷是否從惡意網(wǎng)站跳轉(zhuǎn)。面試官說(shuō)Referer是可以被修改的啊,那怎么辦,問(wèn)倒+10086...,后面面試官繼續(xù)引導(dǎo),說(shuō)可以通過(guò)添加校驗(yàn)token的方法,因?yàn)檗D(zhuǎn)賬肯定是一個(gè)post請(qǐng)求,可以在每次走正常轉(zhuǎn)賬流程的過(guò)程中,從服務(wù)器獲取這個(gè)token,當(dāng)發(fā)起轉(zhuǎn)賬請(qǐng)求時(shí)把token發(fā)送過(guò)去驗(yàn)證,而偽造請(qǐng)求無(wú)法獲取到這個(gè)token,提交的請(qǐng)求就會(huì)少了這個(gè)token而驗(yàn)證失敗。
后面又問(wèn)了XSS,跨站腳本攻擊,回答了可以通過(guò)劫持服務(wù)器放回的html,在里面插入一段js實(shí)現(xiàn)XSS,面試官說(shuō)這是劫持攻擊...,又問(wèn)了怎么預(yù)防劫持,答不知道,說(shuō)可以用HTTPS,挖了坑給自己跳..一時(shí)也忘記了XSS是怎么攻擊的,后來(lái)面試官說(shuō)XSS是最基本最應(yīng)該知道最常見(jiàn)的一種攻擊方法,遺憾,之前的了解不夠深入,只能現(xiàn)在補(bǔ)課:
1.在一個(gè)沒(méi)經(jīng)過(guò)轉(zhuǎn)義處理的表單,在里面寫(xiě)一個(gè)<script>code...</script>,表單提交,script標(biāo)簽中的代碼被立即執(zhí)行。利用JS可以獲取用戶cookie這一點(diǎn),拿到用戶的cookie,從而拿到用戶的隱私信息。
2.如果一個(gè)論壇的編輯器沒(méi)有做轉(zhuǎn)義處理,假設(shè)你發(fā)布了一篇含有<script>code...</script>的文章,那么所有點(diǎn)開(kāi)這篇文章的人打開(kāi)瞬間都會(huì)執(zhí)行這段script腳本。那么就會(huì)出現(xiàn)大量用戶中招的情況。
解決方法:
1.在js中使用innerHTML方法修改dom的時(shí)候,要對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)義
2.對(duì)cookie設(shè)置httponly即只有后端可以獲取cookie,前端無(wú)法讀寫(xiě),防范cookie被盜用。
6. 跨域問(wèn)題
有沒(méi)有遇到跨域問(wèn)題,為什么會(huì)跨域,瀏覽器同源策略,解決方法:說(shuō)了JSONP,JSONP能不能發(fā)Post請(qǐng)求,CORS,CORS怎么實(shí)現(xiàn)的跨域,CORS的兼容性,IE9+可用,說(shuō)成IE10+可用...,除了這兩種還有什么跨域方式,說(shuō)了HTML5的postMessage,有沒(méi)有用過(guò),沒(méi)有...,還有什么跨域解決方法,iframe解決跨域,修改domain實(shí)現(xiàn)跨域,iframe跨域能不能發(fā)起Post請(qǐng)求,答不可以,面試官繼續(xù)引導(dǎo),說(shuō)可以,通過(guò)iframe+form實(shí)現(xiàn)跨域無(wú)刷新post請(qǐng)求。這個(gè)方法的應(yīng)用場(chǎng)景是
需要做post跨域請(qǐng)求 => 想到form可以做跨域post請(qǐng)求 => form提交會(huì)導(dǎo)致頁(yè)面刷新 => 把form提交到iframe就不會(huì)導(dǎo)致頁(yè)面刷新 => 讓這個(gè)iframe把form提交到后臺(tái) => iframe拿到數(shù)據(jù)后再返回給主頁(yè)面
因?yàn)閕frame被我們隱藏了,所以iframe的刷新我們看不到,以此實(shí)現(xiàn)post無(wú)刷新提交。
兩個(gè)跨域問(wèn)題就是post請(qǐng)求跨域(用form+iframe解決),主頁(yè)面與iframe間的跨域(用修改domain解決)
iframe解決post跨域之前真的沒(méi)做了解,跪了跪了。
7.有沒(méi)有做過(guò)登錄驗(yàn)證
這個(gè)被問(wèn)到的時(shí)候不知道什么是登錄驗(yàn)證,以為是cookie記住登錄態(tài)這種問(wèn)題,一番搜索才知道,面試官應(yīng)該是想要我回答前后端分離如何做到登錄驗(yàn)證,回答JWT(JSON Web Token)之類(lèi)的登錄驗(yàn)證。
傳統(tǒng)的后端記住用戶登錄態(tài)是利用seesion保存用戶信息,然后返回一個(gè)cookie,每次進(jìn)入網(wǎng)頁(yè)用cookie驗(yàn)證服務(wù)端是否有保存這個(gè)用戶的session,這樣每多一個(gè)用戶就要增加一個(gè)session,服務(wù)端的開(kāi)銷(xiāo)會(huì)越來(lái)越大。
JWT是一種基于Token的登錄驗(yàn)證方法,使用JWT,服務(wù)端不再需要保存session,只要對(duì)客服端返回的用戶信息進(jìn)行加密,再把經(jīng)過(guò)加密的Token返回給客戶端,客戶端將Token保存在cookie(并設(shè)置httponly)或localStorage內(nèi),每次對(duì)后端做請(qǐng)求的時(shí)候都把Token放在請(qǐng)求頭的Authorization字段中,服務(wù)端收到這個(gè)字段,對(duì)Token進(jìn)行解密,知道你是哪個(gè)用戶后放回相應(yīng)的請(qǐng)求內(nèi)容。
大致流程如下:

8. 反向代理
反向代理也是前端的東西!?
一番搜索后發(fā)現(xiàn)其實(shí)也不難理解,但是面試時(shí)聽(tīng)到反向代理也只知道nginx是做反向代理的,往深了說(shuō)并不了解...
說(shuō)反向代理,先從用戶使用代理服務(wù)器說(shuō)起,代理服務(wù)器的作用即,當(dāng)我想要訪問(wèn)某個(gè)網(wǎng)站的時(shí)候,出于不想讓網(wǎng)站知道誰(shuí)訪問(wèn)了它的目的,我先進(jìn)過(guò)一個(gè)代理服務(wù)器,讓代理服務(wù)器去訪問(wèn)這個(gè)網(wǎng)站,代理服務(wù)器再把網(wǎng)站的請(qǐng)求結(jié)果返回給我。
反向代理即不是用戶設(shè)置代理服務(wù)器,而是服務(wù)端自己加了一層代理服務(wù)器,用戶訪問(wèn)網(wǎng)站的時(shí)候,先不直接訪問(wèn)真實(shí)的服務(wù)器,先過(guò)代理服務(wù)器。
這樣做的好處有3個(gè):
- 安全過(guò)濾
先確認(rèn)該用戶是真實(shí)用戶還是攻擊,請(qǐng)求信息是否有危害網(wǎng)站的內(nèi)容,沒(méi)問(wèn)題再轉(zhuǎn)向真實(shí)服務(wù)器。
2.內(nèi)容緩存
緩存服務(wù)器就相當(dāng)于反向代理服務(wù)器的作用了,用戶不用訪問(wèn)真實(shí)服務(wù)器就能拿到資源,減少真實(shí)服務(wù)器的負(fù)擔(dān)。
3.負(fù)載均衡
當(dāng)服務(wù)器有多臺(tái)時(shí),先經(jīng)過(guò)反向代理服務(wù)器,讓方向代理服務(wù)器判斷當(dāng)前哪臺(tái)服務(wù)器空閑,就把請(qǐng)求轉(zhuǎn)到哪臺(tái)服務(wù)器,實(shí)現(xiàn)負(fù)載均衡。
大問(wèn)題就問(wèn)這么多,全程38分鐘,說(shuō)實(shí)話覺(jué)得所有問(wèn)題都回答得很一般??嫉闹R(shí)點(diǎn)基本是JS,CSS之外的網(wǎng)絡(luò),或者實(shí)際工作中的一些策略性問(wèn)題,這方面自己確實(shí)是很薄弱的,需要再深入研究。還是很開(kāi)心能有這次的面試機(jī)會(huì)!
以上知識(shí)點(diǎn)復(fù)習(xí)參考了以下文章:
瀏覽器緩存知識(shí)小結(jié)及應(yīng)用
跨站請(qǐng)求偽造-維基百科
XSS的原理分析與解剖
前端xss攻擊
iframe跨域POST提交
iframe實(shí)現(xiàn)跨域post請(qǐng)求的技術(shù)細(xì)節(jié)
使用隱藏iframe進(jìn)行表單跨域提交的方法封裝
淺談前端登錄認(rèn)證機(jī)制
前后端分離,前端如何判斷登錄狀態(tài)?
基于 Token 的身份驗(yàn)證
適用于前后端分離的下一代認(rèn)證機(jī)制 —— JSON Web Token(譯) · Issue #1 · smilingsun/blog
什么是反向代理服務(wù)器 | 程序師