Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
言
本文主要給大家?guī)?lái)一些我面試的經(jīng)歷和經(jīng)驗(yàn),希望對(duì)正在求職的同學(xué)有所幫助。我先大致說(shuō)下面試之前的個(gè)人情況:2017年7月正式入職??低晹?shù)字技術(shù)股份有限公司,使用Vue.js技術(shù)棧。
我寫(xiě)的篇幅可能有點(diǎn)長(zhǎng),如果只想看成功的面試請(qǐng)直接從阿里企業(yè)智能事業(yè)部(一面)開(kāi)始,大家見(jiàn)諒哈。
關(guān)于阿里
Hi,大家好,我們是阿里巴巴新成立的BU,目前還有大量的Web前端職位空缺,機(jī)會(huì)難得,希望正在找工作的同學(xué)們可以來(lái)試試:
真的機(jī)會(huì)難得哦,如果想更多了解我們BU以及找我內(nèi)推的同事加我釘釘或者微信(純粹找我了解或者溝通技術(shù)也行,啊哈哈):18768107826
簡(jiǎn)歷
我的簡(jiǎn)歷只是簡(jiǎn)單的用MD做了一份,大致包含了以下幾個(gè)部分:
小提示:在基本資料里一定要填寫(xiě)正確的郵箱地址,我在前期面試的時(shí)候都沒(méi)有打開(kāi)郵箱查看面試情況,導(dǎo)致一些面試的時(shí)間點(diǎn)和面試結(jié)果都不清楚(一直以為會(huì)發(fā)短信通知)。
如果去現(xiàn)場(chǎng)面試,一定要記得帶上筆和簡(jiǎn)歷。一方面你給面試官的簡(jiǎn)歷必定是最新的(在不斷面試的過(guò)程中你必定會(huì)修改簡(jiǎn)歷),另一方面這也會(huì)給面試官一種非常舒心的感覺(jué)。
對(duì)于簡(jiǎn)歷這里提一點(diǎn),在寫(xiě)自己的專(zhuān)業(yè)技能和項(xiàng)目經(jīng)歷時(shí)盡量不要給自己挖坑,這里展示一下我的專(zhuān)業(yè)技能(我會(huì)的不多):
切忌寫(xiě)一大堆讓人感覺(jué)花里胡哨的技能,尤其是一些很淺顯的技能(基本技能除外)。如果你有一些別人很難替代的技能,那這些技能就是亮點(diǎn)了,我這里就沒(méi)什么亮點(diǎn)技能。有些技能你會(huì)但是不熟練,你可以適當(dāng)?shù)脑谀愕?strong>項(xiàng)目經(jīng)歷中體現(xiàn)出來(lái)。對(duì)于項(xiàng)目經(jīng)歷盡量挑自己覺(jué)得非常有技術(shù)含量的項(xiàng)目進(jìn)行說(shuō)明(寧缺毋濫),對(duì)于自己參加過(guò)但不是特別熟悉的項(xiàng)目盡量不要填寫(xiě),防止給自己挖坑。
小提示:這里附上的我的面試簡(jiǎn)歷供大家參考。感謝jsliang的文章2019 面試系列 - 簡(jiǎn)歷,大家制作簡(jiǎn)歷時(shí)也可以參考這篇文章。
在投遞簡(jiǎn)歷時(shí)大家千萬(wàn)不要被招聘信息中的要求嚇到,記得有一次投遞簡(jiǎn)歷時(shí)我對(duì)招聘者說(shuō)自身不太符合要求,招聘者當(dāng)時(shí)說(shuō)要求都是唬人的,覺(jué)得有興趣就投,有些招聘要求可能正是你未來(lái)學(xué)習(xí)或者深入的領(lǐng)域。
面試
簡(jiǎn)歷制作完后我大概投了四家公司:有贊、滴滴、51信用卡和阿里。其中有贊掛在二面,滴滴掛在一面,51信用卡掛在一面,阿里兩個(gè)部門(mén)掛在一面,一個(gè)部門(mén)面試成功。很多面試者的經(jīng)歷可能都是像我這樣,在一次次的面試失敗中不斷的總結(jié)進(jìn)步,最終拿到理想的Offer。
小提示:建議大家在投遞簡(jiǎn)歷時(shí)可以先投遞一些試水的小公司,先檢驗(yàn)一下自己是不是可以勝任這些公司的面試。同時(shí)在每一次面試完后記得把面試官提問(wèn)的問(wèn)題記錄下來(lái),對(duì)于沒(méi)有答上來(lái)的問(wèn)題還是要好好搞懂或者實(shí)踐一下,因?yàn)楹苡锌赡芟乱患业拿嬖嚬贂?huì)問(wèn)同樣的問(wèn)題。
在面試的過(guò)程中,這里我給出幾點(diǎn)意見(jiàn):
接下來(lái)我會(huì)按照面試順序給出面試題以及自己理解的一些答案:
有贊(一面)
說(shuō)說(shuō)CSS選擇器以及這些選擇器的優(yōu)先級(jí)
你知道什么是BFC么
小提示:這個(gè)問(wèn)題重點(diǎn)是BFC是什么,BFC觸發(fā)的條件有哪些,BFC可以干什么。這里我試著講解了一下Boostrap的清除浮動(dòng)(display:table創(chuàng)建匿名table-cell間接觸發(fā)BFC),如果有看到別的場(chǎng)景使用或者自身有使用的場(chǎng)景可以嘗試講解一下使用技巧。這樣可以讓面試官覺(jué)得你不僅僅知道他問(wèn)的東西是什么,你還能很好的使用它。
什么是BFC
BFC 全稱(chēng)為塊級(jí)格式化上下文 (Block Formatting Context) 。BFC是 W3C CSS 2.1 規(guī)范中的一個(gè)概念,它決定了元素如何對(duì)其內(nèi)容進(jìn)行定位以及與其他元素的關(guān)系和相互作用,當(dāng)涉及到可視化布局的時(shí)候,Block Formatting Context提供了一個(gè)環(huán)境,HTML元素在這個(gè)環(huán)境中按照一定規(guī)則進(jìn)行布局。一個(gè)環(huán)境中的元素不會(huì)影響到其它環(huán)境中的布局。比如浮動(dòng)元素會(huì)形成BFC,浮動(dòng)元素內(nèi)部子元素的主要受該浮動(dòng)元素影響,兩個(gè)浮動(dòng)元素之間是互不影響的。這里有點(diǎn)類(lèi)似一個(gè)BFC就是一個(gè)獨(dú)立的行政單位的意思??梢哉f(shuō)BFC就是一個(gè)作用范圍,把它理解成是一個(gè)獨(dú)立的容器,并且這個(gè)容器里box的布局與這個(gè)容器外的box毫不相干。
觸發(fā)BFC的條件
BFC的約束規(guī)則
BFC可以解決的問(wèn)題
了解盒模型么
包括內(nèi)容區(qū)域、內(nèi)邊距區(qū)域、邊框區(qū)域和外邊距區(qū)域。
box-sizing: content-box(W3C盒子模型):元素的寬高大小表現(xiàn)為內(nèi)容的大小。box-sizing: border-box(IE盒子模型):元素的寬高表現(xiàn)為內(nèi)容 + 內(nèi)邊距 + 邊框的大小。背景會(huì)延伸到邊框的外沿。
IE5.x和IE6在怪異模式中使用非標(biāo)準(zhǔn)的盒子模型,這些瀏覽器的width屬性不是內(nèi)容的寬度,而是內(nèi)容、內(nèi)邊距和邊框的寬度的總和。
如何實(shí)現(xiàn)左側(cè)寬度固定,右側(cè)寬度自適應(yīng)的布局
小提示:這個(gè)問(wèn)題面試官會(huì)要求說(shuō)出幾種解決方法。
DOM結(jié)構(gòu)
<divclass="box"><divclass="box-left"></div><divclass="box-right"></div></div>
利用float + margin實(shí)現(xiàn)
.box { height: 200px; } .box > div { height: 100%; } .box-left { width: 200px; float: left; background-color: blue; } .box-right { margin-left: 200px; background-color: red; }
利用calc計(jì)算寬度
.box { height: 200px; } .box > div { height: 100%; } .box-left { width: 200px; float: left; background-color: blue; } .box-right { width: calc(100% - 200px); float: right; background-color: red; }
利用float + overflow實(shí)現(xiàn)
.box { height: 200px; } .box > div { height: 100%; } .box-left { width: 200px; float: left; background-color: blue; } .box-right { overflow: hidden; background-color: red; }
利用flex實(shí)現(xiàn)
這里不是最佳答案,應(yīng)該是使用flex-basis實(shí)現(xiàn)更合理
.box { height: 200px; display: flex; } .box > div { height: 100%; } .box-left { width: 200px; background-color: blue; } .box-right { flex: 1; // 設(shè)置flex-grow屬性為1,默認(rèn)為0 overflow: hidden; background-color: red; }
了解跨域嗎,一般什么情況下會(huì)導(dǎo)致跨域
小提示:如果平常自身有使用場(chǎng)景可結(jié)合使用場(chǎng)景進(jìn)行講解,比如我在這里使用過(guò)的場(chǎng)景是CORS和Nginx反向代理。
跨域行為
JSONP
小提示:如果你提到JSONP,面試官肯定會(huì)問(wèn)你整個(gè)詳細(xì)的實(shí)現(xiàn)過(guò)程,所以一定要搞懂JSONP的實(shí)現(xiàn)原理,如果不是很理解可以自己起一個(gè)Express服務(wù)實(shí)踐一下。
Web前端事先定義一個(gè)用于獲取跨域響應(yīng)數(shù)據(jù)的回調(diào)函數(shù),并通過(guò)沒(méi)有同源策略限制的script標(biāo)簽發(fā)起一個(gè)請(qǐng)求(將回調(diào)函數(shù)的名稱(chēng)放到這個(gè)請(qǐng)求的query參數(shù)里),然后服務(wù)端返回這個(gè)回調(diào)函數(shù)的執(zhí)行,并將需要響應(yīng)的數(shù)據(jù)放到回調(diào)函數(shù)的參數(shù)里,前端的script標(biāo)簽請(qǐng)求到這個(gè)執(zhí)行的回調(diào)函數(shù)后會(huì)立馬執(zhí)行,于是就拿到了執(zhí)行的響應(yīng)數(shù)據(jù)。
缺點(diǎn):JSONP只能發(fā)起GET請(qǐng)求
如何實(shí)現(xiàn)一個(gè)JSONP
這里給出幾個(gè)鏈接:
JSONP安全性問(wèn)題
CSRF攻擊
前端構(gòu)造一個(gè)惡意頁(yè)面,請(qǐng)求JSONP接口,收集服務(wù)端的敏感信息。如果JSONP接口還涉及一些敏感操作或信息(比如登錄、刪除等操作),那就更不安全了。
解決方法:驗(yàn)證JSONP的調(diào)用來(lái)源(Referer),服務(wù)端判斷Referer是否是白名單,或者部署隨機(jī)Token來(lái)防御。
XSS漏洞
不嚴(yán)謹(jǐn)?shù)?content-type導(dǎo)致的 XSS 漏洞,想象一下 JSONP 就是你請(qǐng)求 http://youdomain.com?callback=douniwan, 然后返回 douniwan({ data }),那假如請(qǐng)求 http://youdomain.com?callback=<script>alert(1)</script> 不就返回 <script>alert(1)</script>({ data })了嗎,如果沒(méi)有嚴(yán)格定義好 Content-Type( Content-Type: application/json ),再加上沒(méi)有過(guò)濾 callback 參數(shù),直接當(dāng) html 解析了,就是一個(gè)赤裸裸的 XSS 了。
解決方法:嚴(yán)格定義 Content-Type: application/json,然后嚴(yán)格過(guò)濾 callback 后的參數(shù)并且限制長(zhǎng)度(進(jìn)行字符轉(zhuǎn)義,例如<換成<,>換成>)等,這樣返回的腳本內(nèi)容會(huì)變成文本格式,腳本將不會(huì)執(zhí)行。
服務(wù)器被黑,返回一串惡意執(zhí)行的代碼
可以將執(zhí)行的代碼轉(zhuǎn)發(fā)到服務(wù)端進(jìn)行校驗(yàn)JSONP內(nèi)容校驗(yàn),再返回校驗(yàn)結(jié)果。
CORS(跨域資款共享)
小提示:如果你回答跨域解決方案CORS,那么面試官一定會(huì)問(wèn)你實(shí)現(xiàn)CORS的響應(yīng)頭信息Access-Control-Allow-Origin。
什么是CORS
CORS(跨域資源共享 Cross-origin resource sharing)允許瀏覽器向跨域服務(wù)器發(fā)出XMLHttpRequest請(qǐng)求,從而克服跨域問(wèn)題,它需要瀏覽器和服務(wù)器的同時(shí)支持。
簡(jiǎn)單請(qǐng)求
請(qǐng)求方法是以下三種方法之一:
HTTP的請(qǐng)求頭信息不超出以下幾種字段:
后端的響應(yīng)頭信息:
非簡(jiǎn)單請(qǐng)求
非簡(jiǎn)單請(qǐng)求是那種對(duì)服務(wù)器有特殊要求的請(qǐng)求,比如請(qǐng)求方法是PUT或DELETE,或者Content-Type字段的類(lèi)型是application/json。非簡(jiǎn)單請(qǐng)求的CORS請(qǐng)求,會(huì)在正式通信之前,增加一次HTTP查詢(xún)請(qǐng)求,稱(chēng)為"預(yù)檢"請(qǐng)求(preflight)。
Access-Control-Request-Method:該字段是必須的,用來(lái)列出瀏覽器的CORS請(qǐng)求會(huì)用到哪些HTTP方法,上例是PUT。
Access-Control-Request-Headers:該字段是一個(gè)逗號(hào)分隔的字符串,指定瀏覽器CORS請(qǐng)求會(huì)額外發(fā)送的頭信息字段,上例是X-Custom-Header。
如果瀏覽器否定了"預(yù)檢"請(qǐng)求,會(huì)返回一個(gè)正常的HTTP回應(yīng),但是沒(méi)有任何CORS相關(guān)的頭信息字段。這時(shí),瀏覽器就會(huì)認(rèn)定,服務(wù)器不同意預(yù)檢請(qǐng)求,因此觸發(fā)一個(gè)錯(cuò)誤,被XMLHttpRequest對(duì)象的onerror回調(diào)函數(shù)捕獲。
JSONP和CORS的對(duì)比
其他跨域解決方案
HTTP2和HTTP1有什么區(qū)別
相對(duì)于HTTP1.0,HTTP1.1的優(yōu)化:
相對(duì)于HTTP1.1,HTTP2的優(yōu)化:
你能說(shuō)說(shuō)緩存么
小提示:如果平常有遇到過(guò)緩存的坑或者很好的利用緩存,可以講解一下自己的使用場(chǎng)景。如果沒(méi)有使用注意過(guò)緩存問(wèn)題你也可以嘗試講解一下和我們息息相關(guān)的Webpack構(gòu)建(每一次構(gòu)建靜態(tài)資源名稱(chēng)的hash值都會(huì)變化),它其實(shí)就跟緩存相關(guān)。有興趣的同學(xué)可以查看張?jiān)讫埖牟┛痛蠊纠镌鯓娱_(kāi)發(fā)和部署前端代碼?。
緩存分為強(qiáng)緩存和協(xié)商緩存。強(qiáng)緩存不過(guò)服務(wù)器,協(xié)商緩存需要過(guò)服務(wù)器,協(xié)商緩存返回的狀態(tài)碼是304。兩類(lèi)緩存機(jī)制可以同時(shí)存在,強(qiáng)緩存的優(yōu)先級(jí)高于協(xié)商緩存。當(dāng)執(zhí)行強(qiáng)緩存時(shí),如若緩存命中,則直接使用緩存數(shù)據(jù)庫(kù)中的數(shù)據(jù),不再進(jìn)行緩存協(xié)商。
強(qiáng)緩存
Expires(HTTP1.0):Exprires的值為服務(wù)端返回的數(shù)據(jù)到期時(shí)間。當(dāng)再次請(qǐng)求時(shí)的請(qǐng)求時(shí)間小于返回的此時(shí)間,則直接使用緩存數(shù)據(jù)。但由于服務(wù)端時(shí)間和客戶(hù)端時(shí)間可能有誤差,這也將導(dǎo)致緩存命中的誤差。另一方面,Expires是HTTP1.0的產(chǎn)物,故現(xiàn)在大多數(shù)使用Cache-Control替代。
缺點(diǎn):使用的是絕對(duì)時(shí)間,如果服務(wù)端和客戶(hù)端的時(shí)間產(chǎn)生偏差,那么會(huì)導(dǎo)致命中緩存產(chǎn)生偏差。
Pragma(HTTP1.0):HTTP1.0時(shí)的遺留字段,當(dāng)值為"no-cache"時(shí)強(qiáng)制驗(yàn)證緩存,Pragma禁用緩存,如果又給Expires定義一個(gè)還未到期的時(shí)間,那么Pragma字段的優(yōu)先級(jí)會(huì)更高。服務(wù)端響應(yīng)添加'Pragma': 'no-cache',瀏覽器表現(xiàn)行為和刷新(F5)類(lèi)似。
Cache-Control(HTTP1.1):有很多屬性,不同的屬性代表的意義也不同:
請(qǐng)注意no-cache指令很多人誤以為是不緩存,這是不準(zhǔn)確的,no-cache的意思是可以緩存,但每次用應(yīng)該去想服務(wù)器驗(yàn)證緩存是否可用。no-store才是不緩存內(nèi)容。當(dāng)在首部字段Cache-Control 有指定 max-age 指令時(shí),比起首部字段 Expires,會(huì)優(yōu)先處理 max-age 指令。命中強(qiáng)緩存的表現(xiàn)形式:Firefox瀏覽器表現(xiàn)為一個(gè)灰色的200狀態(tài)碼。Chrome瀏覽器狀態(tài)碼表現(xiàn)為200 (from disk cache)或是200 OK (from memory cache)。
協(xié)商緩存
協(xié)商緩存需要進(jìn)行對(duì)比判斷是否可以使用緩存。瀏覽器第一次請(qǐng)求數(shù)據(jù)時(shí),服務(wù)器會(huì)將緩存標(biāo)識(shí)與數(shù)據(jù)一起響應(yīng)給客戶(hù)端,客戶(hù)端將它們備份至緩存中。再次請(qǐng)求時(shí),客戶(hù)端會(huì)將緩存中的標(biāo)識(shí)發(fā)送給服務(wù)器,服務(wù)器根據(jù)此標(biāo)識(shí)判斷。若未失效,返回304狀態(tài)碼,瀏覽器拿到此狀態(tài)碼就可以直接使用緩存數(shù)據(jù)了。
Last-Modified:服務(wù)器在響應(yīng)請(qǐng)求時(shí),會(huì)告訴瀏覽器資源的最后修改時(shí)間。
if-Modified-Since:瀏覽器再次請(qǐng)求服務(wù)器的時(shí)候,請(qǐng)求頭會(huì)包含此字段,后面跟著在緩存中獲得的最后修改時(shí)間。服務(wù)端收到此請(qǐng)求頭發(fā)現(xiàn)有if-Modified-Since,則與被請(qǐng)求資源的最后修改時(shí)間進(jìn)行對(duì)比,如果一致則返回304和響應(yīng)報(bào)文頭,瀏覽器只需要從緩存中獲取信息即可。
if-Unmodified-Since: 從某個(gè)時(shí)間點(diǎn)算起, 是否文件沒(méi)有被修改,使用的是相對(duì)時(shí)間,不需要關(guān)心客戶(hù)端和服務(wù)端的時(shí)間偏差。
這兩個(gè)的區(qū)別是一個(gè)是修改了才下載一個(gè)是沒(méi)修改才下載。如果在服務(wù)器上,一個(gè)資源被修改了,但其實(shí)際內(nèi)容根本沒(méi)發(fā)生改變,會(huì)因?yàn)長(zhǎng)ast-Modified時(shí)間匹配不上而返回了整個(gè)實(shí)體給客戶(hù)端(即使客戶(hù)端緩存里有個(gè)一模一樣的資源)。為了解決這個(gè)問(wèn)題,HTTP1.1推出了Etag。
Etag:服務(wù)器響應(yīng)請(qǐng)求時(shí),通過(guò)此字段告訴瀏覽器當(dāng)前資源在服務(wù)器生成的唯一標(biāo)識(shí)(生成規(guī)則由服務(wù)器決定)
If-Match:條件請(qǐng)求,攜帶上一次請(qǐng)求中資源的ETag,服務(wù)器根據(jù)這個(gè)字段判斷文件是否有新的修改
If-None-Match:再次請(qǐng)求服務(wù)器時(shí),瀏覽器的請(qǐng)求報(bào)文頭部會(huì)包含此字段,后面的值為在緩存中獲取的標(biāo)識(shí)。服務(wù)器接收到次報(bào)文后發(fā)現(xiàn)If-None-Match則與被請(qǐng)求資源的唯一標(biāo)識(shí)進(jìn)行對(duì)比。
但是實(shí)際應(yīng)用中由于Etag的計(jì)算是使用算法來(lái)得出的,而算法會(huì)占用服務(wù)端計(jì)算的資源,所有服務(wù)端的資源都是寶貴的,所以就很少使用Etag了。
緩存場(chǎng)景
對(duì)于大部分的場(chǎng)景都可以使用強(qiáng)緩存配合協(xié)商緩存解決,但是在一些特殊的地方可能需要選擇特殊的緩存策略
能說(shuō)說(shuō)首屏加載優(yōu)化有哪些方案么
小提示:如果做過(guò)類(lèi)似優(yōu)化的同學(xué),可能就比較好回答,沒(méi)有做過(guò)類(lèi)似優(yōu)化的同學(xué)可以重點(diǎn)講解一下懶加載(當(dāng)然我這里被面試官追問(wèn)過(guò)懶加載的Webpack配置問(wèn)題)。同時(shí)不知道使用Vue技術(shù)棧的同學(xué)們有沒(méi)有仔細(xì)觀察過(guò)Vue CLI 3構(gòu)建的html文件中的link標(biāo)簽的rel屬性。
如何在Node端配置路徑別名(類(lèi)似于Webpack中的alias配置)
參考
這種問(wèn)題還是附上參考鏈接
談?wù)勀銓?duì)作用域鏈的理解
小提示:同類(lèi)型的問(wèn)題還可以是原型鏈、繼承、閉包等,這種概念性的問(wèn)題你肯定不是一句兩句能說(shuō)清楚的,建議在理解之后自己嘗試總結(jié)一下,如何把重要的知識(shí)點(diǎn)用簡(jiǎn)短的話(huà)語(yǔ)說(shuō)明白。
了解作用域鏈之前我們要知道一下幾個(gè)概念:
函數(shù)的生命周期:
創(chuàng)建:JS解析引擎進(jìn)行預(yù)解析,會(huì)將函數(shù)聲明提前,同時(shí)將該函數(shù)放到全局作用域中或當(dāng)前函數(shù)的上一級(jí)函數(shù)的局部作用域中。
執(zhí)行:JS引擎會(huì)將當(dāng)前函數(shù)的局部變量和內(nèi)部函數(shù)進(jìn)行聲明提前,然后再執(zhí)行業(yè)務(wù)代碼,當(dāng)函數(shù)執(zhí)行完退出時(shí),釋放該函數(shù)的執(zhí)行上下文,并注銷(xiāo)該函數(shù)的局部變量。
變量和函數(shù)的聲明:如果變量名和函數(shù)名聲明時(shí)相同,函數(shù)優(yōu)先聲明。
Activetion Object(AO)、Variable Object(VO):
VO對(duì)應(yīng)的是函數(shù)創(chuàng)建階段,JS解析引擎進(jìn)行預(yù)解析時(shí),所有的變量和函數(shù)的聲明,統(tǒng)稱(chēng)為Variable Object。該變量與執(zhí)行上下文相關(guān),知道自己的數(shù)據(jù)存儲(chǔ)在哪里,并且知道如何訪問(wèn)。VO是一個(gè)與執(zhí)行上下文相關(guān)的特殊對(duì)象,它存儲(chǔ)著在上下文中聲明的以下內(nèi)容:
AO對(duì)應(yīng)的是函數(shù)執(zhí)行階段,當(dāng)函數(shù)被調(diào)用執(zhí)行時(shí),會(huì)建立一個(gè)執(zhí)行上下文,該執(zhí)行上下文包含了函數(shù)所需的所有變量,該變量共同組成了一個(gè)新的對(duì)象就是Activetion Object。該對(duì)象包含了:
作用域鏈:
當(dāng)代碼在一個(gè)環(huán)境中創(chuàng)建時(shí),會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈(scope chain)來(lái)保證對(duì)執(zhí)行環(huán)境有權(quán)訪問(wèn)的變量和函數(shù)。作用域第一個(gè)對(duì)象始終是當(dāng)前執(zhí)行代碼所在環(huán)境的變量對(duì)象(VO)。如果是函數(shù)執(zhí)行階段,那么將其activation object(AO)作為作用域鏈第一個(gè)對(duì)象,第二個(gè)對(duì)象是上級(jí)函數(shù)的執(zhí)行上下文AO,下一個(gè)對(duì)象依次類(lèi)推。
在《JavaScript深入之變量對(duì)象》中講到,當(dāng)查找變量的時(shí)候,會(huì)先從當(dāng)前上下文的變量對(duì)象中查找,如果沒(méi)有找到,就會(huì)從父級(jí)(詞法層面上的父級(jí))執(zhí)行上下文的變量對(duì)象中查找,一直找到全局上下文的變量對(duì)象,也就是全局對(duì)象。這樣由多個(gè)執(zhí)行上下文的變量對(duì)象構(gòu)成的鏈表就叫做作用域鏈。
你知道null和undefined有什么區(qū)別么
閉包有什么作用
Vue響應(yīng)式原理
小提示:如果面試者使用的是Vue技術(shù)棧,那么響應(yīng)式原理是一個(gè)必問(wèn)的問(wèn)題,同時(shí)面試官經(jīng)常也會(huì)問(wèn)Vue 3.0在響應(yīng)式原理上的優(yōu)化方案。
如果對(duì)于響應(yīng)式原理不是很清楚可以查看我之前寫(xiě)的文章基于Vue實(shí)現(xiàn)一個(gè)簡(jiǎn)易MVVM/數(shù)據(jù)劫持的實(shí)現(xiàn)。
了解Event Loop么
小提示:這個(gè)題目問(wèn)到的概率還是蠻大的,這里面試官詢(xún)問(wèn)了我瀏覽器端和Node端的Event Loop有什么不同點(diǎn)。如果想要知道更多瀏覽器端的Event Loop機(jī)制可以查看我之前寫(xiě)的文章你真的理解$nextTick么/JS引擎線程和事件觸發(fā)線程/事件循環(huán)機(jī)制。
事件觸發(fā)線程管理的任務(wù)隊(duì)列是如何產(chǎn)生的呢?事實(shí)上這些任務(wù)就是從JS引擎線程本身產(chǎn)生的,主線程在運(yùn)行時(shí)會(huì)產(chǎn)生執(zhí)行棧,棧中的代碼調(diào)用某些異步API時(shí)會(huì)在任務(wù)隊(duì)列中添加事件,棧中的代碼執(zhí)行完畢后,就會(huì)讀取任務(wù)隊(duì)列中的事件,去執(zhí)行事件對(duì)應(yīng)的回調(diào)函數(shù),如此循環(huán)往復(fù),形成事件循環(huán)機(jī)制。JS中有兩種任務(wù)類(lèi)型:微任務(wù)(microtask)和宏任務(wù)(macrotask),在ES6中,microtask稱(chēng)為 jobs,macrotask稱(chēng)為 task:
Node.js中Event Loop和瀏覽器中Event Loop有什么區(qū)別
┌───────────────────────┐ ┌─>│ timers │<————— 執(zhí)行 setTimeout()、setInterval() 的回調(diào) │ └──────────┬────────────┘ | |<-- 執(zhí)行所有 NextTickQueue 以及 MicroTaskQueue 的回調(diào) │ ┌──────────┴────────────┐ │ │ pendingcallbacks │<————— 執(zhí)行由上一個(gè) Tick 延遲下來(lái)的 I/O 回調(diào)(待完善,可忽略) │ └──────────┬────────────┘ | |<-- 執(zhí)行所有 NextTickQueue 以及 MicroTaskQueue 的回調(diào) │ ┌──────────┴────────────┐ │ │ idle, prepare │<————— 內(nèi)部調(diào)用(可忽略) │ └──────────┬────────────┘ | |<-- 執(zhí)行所有 NextTickQueue 以及 MicroTaskQueue 的回調(diào) | | ┌───────────────┐ │ ┌──────────┴────────────┐ │ incoming: │ - (執(zhí)行幾乎所有的回調(diào),除了 closecallbacks、timers、setImmediate) │ │ poll │<─────┤ connections, │ │ └──────────┬────────────┘ │ data, etc. │ │ | | | | | └───────────────┘ | |<-- 執(zhí)行所有 NextTickQueue 以及 MicroTaskQueue 的回調(diào) | ┌──────────┴────────────┐ │ │ check │<————— setImmediate() 的回調(diào)將會(huì)在這個(gè)階段執(zhí)行 │ └──────────┬────────────┘ | |<-- 執(zhí)行所有 NextTickQueue 以及 MicroTaskQueue 的回調(diào) │ ┌──────────┴────────────┐ └──┤ closecallbacks │<————— socket.on('close', ...) └───────────────────────┘
Node.js中宏任務(wù)分成了幾種類(lèi)型,并且放在了不同的task queue里。不同的task queue在執(zhí)行順序上也有區(qū)別,微任務(wù)放在了每個(gè)task queue的末尾:
如何避免回流和重繪
瀏覽器渲染過(guò)程
瀏覽器渲染過(guò)程如下:
何時(shí)觸發(fā)回流和重繪
何時(shí)發(fā)生回流:
何時(shí)發(fā)生重繪(回流一定會(huì)觸發(fā)重繪):
當(dāng)頁(yè)面中元素樣式的改變并不影響它在文檔流中的位置時(shí)(例如:color、background-color、visibility等),瀏覽器會(huì)將新樣式賦予給元素并重新繪制它,這個(gè)過(guò)程稱(chēng)為重繪。
有時(shí)即使僅僅回流一個(gè)單一的元素,它的父元素以及任何跟隨它的元素也會(huì)產(chǎn)生回流。現(xiàn)代瀏覽器會(huì)對(duì)頻繁的回流或重繪操作進(jìn)行優(yōu)化,瀏覽器會(huì)維護(hù)一個(gè)隊(duì)列,把所有引起回流和重繪的操作放入隊(duì)列中,如果隊(duì)列中的任務(wù)數(shù)量或者時(shí)間間隔達(dá)到一個(gè)閾值的,瀏覽器就會(huì)將隊(duì)列清空,進(jìn)行一次批處理,這樣可以把多次回流和重繪變成一次。你訪問(wèn)以下屬性或方法時(shí),瀏覽器會(huì)立刻清空隊(duì)列:
以上屬性和方法都需要返回最新的布局信息,因此瀏覽器不得不清空隊(duì)列,觸發(fā)回流重繪來(lái)返回正確的值。因此,我們?cè)谛薷臉邮降臅r(shí)候,**最好避免使用上面列出的屬性,他們都會(huì)刷新渲染隊(duì)列。**如果要使用它們,最好將值緩存起來(lái)。
如何避免觸發(fā)回流和重繪
CSS:
JavaScript:
有贊(二面)
小提示:進(jìn)入現(xiàn)場(chǎng)面試需要注意好好準(zhǔn)備自己的簡(jiǎn)歷,面試官一般會(huì)根據(jù)項(xiàng)目進(jìn)行問(wèn)答。
筆試題環(huán)節(jié)
一開(kāi)始面試官就發(fā)了兩張筆試題試卷,總共四道題目,大致考了以下知識(shí)點(diǎn):
項(xiàng)目問(wèn)答環(huán)節(jié)
答完試卷面試官就開(kāi)始問(wèn)簡(jiǎn)歷上的一些項(xiàng)目,我記得其中幾個(gè)問(wèn)題如下(事實(shí)上他問(wèn)的一些問(wèn)題和簡(jiǎn)歷不是很相關(guān)):
我當(dāng)場(chǎng)就感受到了面試官問(wèn)的問(wèn)題很敷衍,可能他覺(jué)得我的簡(jiǎn)歷不夠好,又或者覺(jué)得我能力不行,接下來(lái)面試官又讓我做了一道算法題...
算法題環(huán)節(jié)
當(dāng)時(shí)沒(méi)做出來(lái),非科班出身可能做這些確實(shí)有些困難,也沒(méi)有系統(tǒng)的學(xué)習(xí),面試官看我很困難的樣子,就換了一道題。
這道題還是做出來(lái)了,畢竟比較簡(jiǎn)單,然后面試官說(shuō)今天先到這里,面試結(jié)果會(huì)在一星期內(nèi)通知,然后回來(lái)的那天晚上就收到了面試沒(méi)過(guò)的通知。
小結(jié)
還是蠻感謝這次現(xiàn)場(chǎng)面試的經(jīng)歷,讓我知道如果自身不夠硬,到哪里都會(huì)很被動(dòng)。面試的好處不僅僅在于檢驗(yàn)自己到底有多少能力,更應(yīng)該發(fā)現(xiàn)自身的不足,同時(shí)不斷的去彌補(bǔ)這些不足。于是我再次捧起之前擱置的《算法導(dǎo)論》,并且創(chuàng)建了一個(gè)算法學(xué)習(xí)演示文檔I-Algorithms,希望可以簡(jiǎn)化《算法導(dǎo)論》的一些理論知識(shí),使大家對(duì)于算法的學(xué)習(xí)可以變得更加系統(tǒng)全面和簡(jiǎn)單,也希望通過(guò)這個(gè)學(xué)習(xí)使得算法面試會(huì)變得更加得心應(yīng)手,希望感興趣的同學(xué)可以star一下。
滴滴(一面)
你知道哪些安全問(wèn)題,如何避免
小提示:這里我簡(jiǎn)單講解了一下Vue中的v-html防范XSS攻擊。
XSS(跨站腳本攻擊)
XSS,即 Cross Site Script,中譯是跨站腳本攻擊;其原本縮寫(xiě)是 CSS,但為了和層疊樣式表(Cascading Style Sheet)有所區(qū)分,因而在安全領(lǐng)域叫做 XSS。
XSS 攻擊是指攻擊者在網(wǎng)站上注入惡意的客戶(hù)端代碼,通過(guò)惡意腳本對(duì)客戶(hù)端網(wǎng)頁(yè)進(jìn)行篡改,從而在用戶(hù)瀏覽網(wǎng)頁(yè)時(shí),對(duì)用戶(hù)瀏覽器進(jìn)行控制或者獲取用戶(hù)隱私數(shù)據(jù)的一種攻擊方式。
攻擊者對(duì)客戶(hù)端網(wǎng)頁(yè)注入的惡意腳本一般包括 JavaScript,有時(shí)也會(huì)包含 HTML 和 Flash。有很多種方式進(jìn)行 XSS 攻擊,但它們的共同點(diǎn)為:將一些隱私數(shù)據(jù)像 cookie、session 發(fā)送給攻擊者,將受害者重定向到一個(gè)由攻擊者控制的網(wǎng)站,在受害者的機(jī)器上進(jìn)行一些惡意操作。
XSS攻擊可以分為3類(lèi):反射型(非持久型)、存儲(chǔ)型(持久型)、基于DOM。
反射型
反射型 XSS 只是簡(jiǎn)單地把用戶(hù)輸入的數(shù)據(jù) “反射” 給瀏覽器,這種攻擊方式往往需要攻擊者誘使用戶(hù)點(diǎn)擊一個(gè)惡意鏈接(攻擊者可以將惡意鏈接直接發(fā)送給受信任用戶(hù),發(fā)送的方式有很多種,比如 email, 網(wǎng)站的私信、評(píng)論等,攻擊者可以購(gòu)買(mǎi)存在漏洞網(wǎng)站的廣告,將惡意鏈接插入在廣告的鏈接中),或者提交一個(gè)表單,或者進(jìn)入一個(gè)惡意網(wǎng)站時(shí),注入腳本進(jìn)入被攻擊者的網(wǎng)站。最簡(jiǎn)單的示例是訪問(wèn)一個(gè)鏈接,服務(wù)端返回一個(gè)可執(zhí)行腳本:
const http=require('http'); functionhandleReequest(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.writeHead(200, {'Content-Type': 'text/html; charset=UTF-8'}); res.write('<script>alert("反射型 XSS 攻擊")</script>'); res.end(); } const server=new http.Server(); server.listen(8001, '127.0.0.1'); server.on('request', handleReequest);
存儲(chǔ)型
存儲(chǔ)型 XSS 會(huì)把用戶(hù)輸入的數(shù)據(jù) "存儲(chǔ)" 在服務(wù)器端,當(dāng)瀏覽器請(qǐng)求數(shù)據(jù)時(shí),腳本從服務(wù)器上傳回并執(zhí)行。這種 XSS 攻擊具有很強(qiáng)的穩(wěn)定性。比較常見(jiàn)的一個(gè)場(chǎng)景是攻擊者在社區(qū)或論壇上寫(xiě)下一篇包含惡意 JavaScript 代碼的文章或評(píng)論,文章或評(píng)論發(fā)表后,所有訪問(wèn)該文章或評(píng)論的用戶(hù),都會(huì)在他們的瀏覽器中執(zhí)行這段惡意的 JavaScript 代碼:
// 例如在評(píng)論中輸入以下留言 // 如果請(qǐng)求這段留言的時(shí)候服務(wù)端不做轉(zhuǎn)義處理,請(qǐng)求之后頁(yè)面會(huì)執(zhí)行這段惡意代碼 <script>alert('xss 攻擊')</script>
基于DOM
基于 DOM 的 XSS 攻擊是指通過(guò)惡意腳本修改頁(yè)面的 DOM 結(jié)構(gòu),是純粹發(fā)生在客戶(hù)端的攻擊:
<h2>XSS: </h2> <input type="text" id="input"> <buttonid="btn">Submit</button> <div id="div"></div> <script> const input=document.getElementById('input'); const btn=document.getElementById('btn'); const div=document.getElementById('div'); let val; input.addEventListener('change', (e)=> { val=e.target.value; }, false); btn.addEventListener('click', ()=> { div.innerHTML=`<a href=${val}>testLink</a>` }, false); </script>
點(diǎn)擊 Submit 按鈕后,會(huì)在當(dāng)前頁(yè)面插入一個(gè)鏈接,其地址為用戶(hù)的輸入內(nèi)容。如果用戶(hù)在輸入時(shí)構(gòu)造了如下內(nèi)容:
onclick=alert(/xss/)
用戶(hù)提交之后,頁(yè)面代碼就變成了:
<a href onlick="alert(/xss/)">testLink</a>
此時(shí),用戶(hù)點(diǎn)擊生成的鏈接,就會(huì)執(zhí)行對(duì)應(yīng)的腳本。
XSS攻擊防范
HttpOnly 防止劫取 Cookie:HttpOnly 最早由微軟提出,至今已經(jīng)成為一個(gè)標(biāo)準(zhǔn)。瀏覽器將禁止頁(yè)面的Javascript 訪問(wèn)帶有 HttpOnly 屬性的Cookie。上文有說(shuō)到,攻擊者可以通過(guò)注入惡意腳本獲取用戶(hù)的 Cookie 信息。通常 Cookie 中都包含了用戶(hù)的登錄憑證信息,攻擊者在獲取到 Cookie 之后,則可以發(fā)起 Cookie 劫持攻擊。所以,嚴(yán)格來(lái)說(shuō),HttpOnly 并非阻止 XSS 攻擊,而是能阻止 XSS 攻擊后的 Cookie 劫持攻擊。
輸入檢查:不要相信用戶(hù)的任何輸入。對(duì)于用戶(hù)的任何輸入要進(jìn)行檢查、過(guò)濾和轉(zhuǎn)義。建立可信任的字符和 HTML 標(biāo)簽白名單,對(duì)于不在白名單之列的字符或者標(biāo)簽進(jìn)行過(guò)濾或編碼。在 XSS 防御中,輸入檢查一般是檢查用戶(hù)輸入的數(shù)據(jù)中是否包含 <,> 等特殊字符,如果存在,則對(duì)特殊字符進(jìn)行過(guò)濾或編碼,這種方式也稱(chēng)為 XSS Filter。而在一些前端框架中,都會(huì)有一份 decodingMap, 用于對(duì)用戶(hù)輸入所包含的特殊字符或標(biāo)簽進(jìn)行編碼或過(guò)濾,如 <,>,script,防止 XSS 攻擊:
// vuejs 中的 decodingMap// 在 vuejs 中,如果輸入帶 script 標(biāo)簽的內(nèi)容,會(huì)直接過(guò)濾掉const decodingMap={ '<': '<', '>': '>', '"': '"', '&': '&', ' ': '\n' }
輸出檢查:用戶(hù)的輸入會(huì)存在問(wèn)題,服務(wù)端的輸出也會(huì)存在問(wèn)題。一般來(lái)說(shuō),除富文本的輸出外,在變量輸出到 HTML 頁(yè)面時(shí),可以使用編碼或轉(zhuǎn)義的方式來(lái)防御 XSS 攻擊。例如利用 sanitize-html 對(duì)輸出內(nèi)容進(jìn)行有規(guī)則的過(guò)濾之后再輸出到頁(yè)面中。
CSRF/XSRF(跨站請(qǐng)求偽造)
CSRF,即 Cross Site Request Forgery,中譯是跨站請(qǐng)求偽造,是一種劫持受信任用戶(hù)向服務(wù)器發(fā)送非預(yù)期請(qǐng)求的攻擊方式。通常情況下,CSRF 攻擊是攻擊者借助受害者的 Cookie 騙取服務(wù)器的信任,可以在受害者毫不知情的情況下以受害者名義偽造請(qǐng)求發(fā)送給受攻擊服務(wù)器,從而在并未授權(quán)的情況下執(zhí)行在權(quán)限保護(hù)之下的操作。
Cookie
Cookie 是服務(wù)器發(fā)送到用戶(hù)瀏覽器并保存在本地的一小塊數(shù)據(jù),它會(huì)在瀏覽器下次向同一服務(wù)器再發(fā)起請(qǐng)求時(shí)被攜帶并發(fā)送到服務(wù)器上。Cookie 主要用于以下三個(gè)方面:
而瀏覽器所持有的 Cookie 分為兩種:
res.setHeader('Set-Cookie', ['mycookie=222', 'test=3333; expires=Sat, 21 Jul 2018 00:00:00 GMT;']);
上述代碼創(chuàng)建了兩個(gè) Cookie:mycookie 和 test,前者屬于會(huì)話(huà)期 Cookie,后者則屬于持久性 Cookie。
CSRF攻擊
使登錄用戶(hù)訪問(wèn)攻擊者的網(wǎng)站,發(fā)起一個(gè)請(qǐng)求,由于 Cookie 中包含了用戶(hù)的認(rèn)證信息,當(dāng)用戶(hù)訪問(wèn)攻擊者準(zhǔn)備的攻擊環(huán)境時(shí),攻擊者就可以對(duì)服務(wù)器發(fā)起 CSRF 攻擊。
在這個(gè)攻擊過(guò)程中,攻擊者借助受害者的 Cookie 騙取服務(wù)器的信任,但并不能拿到 Cookie,也看不到 Cookie 的內(nèi)容。而對(duì)于服務(wù)器返回的結(jié)果,由于瀏覽器同源策略的限制,攻擊者也無(wú)法進(jìn)行解析。(攻擊者的網(wǎng)站雖然是跨域的,但是他構(gòu)造的鏈接是源網(wǎng)站的,跟源網(wǎng)站是同源的,所以能夠攜帶cookie發(fā)起訪問(wèn))。
但是攻擊者無(wú)法從返回的結(jié)果中得到任何東西,他所能做的就是給服務(wù)器發(fā)送請(qǐng)求,以執(zhí)行請(qǐng)求中所描述的命令,在服務(wù)器端直接改變數(shù)據(jù)的值,而非竊取服務(wù)器中的數(shù)據(jù)。例如刪除數(shù)據(jù)、修改數(shù)據(jù),新增數(shù)據(jù)等,無(wú)法獲取數(shù)據(jù)。
CSRF攻擊防范
驗(yàn)證碼:驗(yàn)證碼被認(rèn)為是對(duì)抗 CSRF 攻擊最簡(jiǎn)潔而有效的防御方法。從上述示例中可以看出,CSRF 攻擊往往是在用戶(hù)不知情的情況下構(gòu)造了網(wǎng)絡(luò)請(qǐng)求。而驗(yàn)證碼會(huì)強(qiáng)制用戶(hù)必須與應(yīng)用進(jìn)行交互,才能完成最終請(qǐng)求。因?yàn)橥ǔG闆r下,驗(yàn)證碼能夠很好地遏制 CSRF 攻擊。但驗(yàn)證碼并不是萬(wàn)能的,因?yàn)槌鲇谟脩?hù)考慮,不能給網(wǎng)站所有的操作都加上驗(yàn)證碼。因此,驗(yàn)證碼只能作為防御 CSRF 的一種輔助手段,而不能作為最主要的解決方案。
Referer Check:根據(jù) HTTP 協(xié)議,在 HTTP 頭中有一個(gè)字段叫 Referer,它記錄了該 HTTP 請(qǐng)求的來(lái)源地址。通過(guò) Referer Check,可以檢查請(qǐng)求是否來(lái)自合法的"源"。
添加token驗(yàn)證:要抵御 CSRF,關(guān)鍵在于在請(qǐng)求中放入攻擊者所不能偽造的信息,并且該信息不存在于 Cookie 之中。可以在 HTTP 請(qǐng)求中以參數(shù)的形式加入一個(gè)隨機(jī)產(chǎn)生的 token,并在服務(wù)器端建立一個(gè)攔截器來(lái)驗(yàn)證這個(gè) token,如果請(qǐng)求中沒(méi)有 token 或者 token 內(nèi)容不正確,則認(rèn)為可能是 CSRF 攻擊而拒絕該請(qǐng)求。
介紹一下Graphql
小提示:這道題是給自己挖了一個(gè)坑,抱著學(xué)習(xí)的心態(tài)嘗試使用Graphql技術(shù),卻沒(méi)有好好理解是在什么場(chǎng)景下為了解決什么問(wèn)題才應(yīng)該使用,也沒(méi)有好好準(zhǔn)備如何描述新技術(shù),往往這種不熟悉的技術(shù)自己在簡(jiǎn)歷中應(yīng)該留存一些心眼,盡量不要提,否則答不上來(lái)會(huì)很尷尬,讓面試官懷疑你的項(xiàng)目成分。
什么是Graphql
GraphQL是一種API查詢(xún)語(yǔ)言。API接口的返回值可以從靜態(tài)變?yōu)閯?dòng)態(tài),即調(diào)用者來(lái)聲明接口返回什么數(shù)據(jù),可以進(jìn)一步解耦前后端。在Graphal中,預(yù)先定義Schema和聲明Type來(lái)達(dá)到動(dòng)態(tài)獲取接口數(shù)據(jù)的目的:
為什么要使用Graphql:
Type(數(shù)據(jù)模型的抽象)
Type簡(jiǎn)單可以分為兩種,一種叫做Scalar Type(標(biāo)量類(lèi)型),另一種叫做Object Type(對(duì)象類(lèi)型):
Scalar Type(標(biāo)量類(lèi)型):內(nèi)建的標(biāo)量包含,String、Int、Float、Boolean、Enum
Object Type(對(duì)象類(lèi)型):感覺(jué)類(lèi)似于TypeScript的接口類(lèi)型
Type Modifier(類(lèi)型修飾符):用于表明是否必填等
Schema(模式)
定義了字段的類(lèi)型、數(shù)據(jù)的結(jié)構(gòu),描述了接口數(shù)據(jù)請(qǐng)求的規(guī)則
Query(查詢(xún)、操作類(lèi)型)
查詢(xún)類(lèi)型:query(查詢(xún))、mutation(更改)和subscription(訂閱)
Resolver(解析函數(shù))
提供相關(guān)Query所返回?cái)?shù)據(jù)的邏輯。Query和與之對(duì)應(yīng)的Resolver是同名的,這樣在GraphQL才能把它們對(duì)應(yīng)起來(lái)。解析的過(guò)程可能是遞歸的,只要遇到非標(biāo)量類(lèi)型,會(huì)嘗試?yán)^續(xù)解析,如果遇到標(biāo)量類(lèi)型,那么解析完成,這個(gè)過(guò)程叫做解析鏈。
說(shuō)說(shuō)Vue中$nextTick的實(shí)現(xiàn)原理
小提示:如果面試者使用的是Vue技術(shù)棧,那么$nextTick的原理是一個(gè)高頻問(wèn)題,面試者借此可以追問(wèn)的東西較多,例如瀏覽器的Event Loop、微任務(wù)和宏任務(wù)、Node.js的Event Loop、異步更新DOM(響應(yīng)式的數(shù)據(jù)for循環(huán)改變了1000次為什么視圖只更新了一次)、$nextTick歷史版本問(wèn)題等等。
這個(gè)如果不是很清楚的具體可查看我之前寫(xiě)的文章你真的理解$nextTick么。
Vue響應(yīng)式原理
談?wù)剬?duì)閉包的理解
JSONP的實(shí)現(xiàn)原理
CSS中的BFC
如何實(shí)現(xiàn)居中
水平居中
// flex容器 <div class="box"> // flex項(xiàng)目 <div class="box-center"> </div> </div> .box { width: 200px; height: 200px; display: flex; // 使內(nèi)部的flex項(xiàng)目水平居中 justify-content: center; background-color: pink; } /* .box-center { width: 50%; background-color: greenyellow; } */
.box { width: 200px; height: 200px; position: relative; background-color: pink; } .box-center { position: absolute; left:50%; // width: 50%; height: 100%; // 通過(guò) translate() 方法,元素從其當(dāng)前位置移動(dòng),根據(jù)給定的 left(x 坐標(biāo)) 和 top(y 坐標(biāo)) 位置參數(shù): // translate(x,y) 定義 2D 轉(zhuǎn)換。 // translateX(x) 定義轉(zhuǎn)換,只是用 X 軸的值。 // translateY(y) 定義轉(zhuǎn)換,只是用 Y 軸的值。 // left: 50% 先整體向父容器的左側(cè)偏移50%,此時(shí)是不能居中的,因?yàn)樵乇旧碛写笮? // 接著使用transform使用百分比向左偏移本身的寬度的一半實(shí)現(xiàn)水平居中(這里的百分比以元素本身的寬高為基準(zhǔn)) transform:translate(-50%,0); background-color: greenyellow; }
.box { width: 200px; height: 200px; position: relative; background-color: pink; } .box-center { position: absolute; left:50%; height: 100%; // 類(lèi)似于transform// width: 50%;// margin-left: -25%; width: 100px; margin-left: -50px; background-color: greenyellow; }
垂直居中
.box { height: 100px; } .box::after, .box-center{ display:inline-block; vertical-align:middle; } .box::after{ content:''; height:100%; }
居中元素高度不定
.box { height: 100px; display: table; } .box-center{ display: table-cell; vertical-align:middle; }
.box { height: 100px; display: flex; align-items: center; }
優(yōu)點(diǎn):內(nèi)容塊的寬高任意, 優(yōu)雅的溢出. 可用于更復(fù)雜高級(jí)的布局技術(shù)中. 缺點(diǎn):IE8/IE9不支持、需要瀏覽器廠商前綴、渲染上可能會(huì)有一些問(wèn)題。
.box { height: 100px; position: relative; background-color: pink; } .box-center { position: absolute; top: 50%; transform: translate(0, -50%); background-color: greenyellow; }
缺點(diǎn):IE8不支持, 屬性需要追加瀏覽器廠商前綴,可能干擾其他 transform 效果,某些情形下會(huì)出現(xiàn)文本或元素邊界渲染模糊的現(xiàn)象。
居中元素高度固定
.box { position:relative; height: 100px; background-color: pink; } .box-center{ position:absolute; top:50%; // 注意不能使用百分比// margin的百分比計(jì)算是相對(duì)于父容器的width來(lái)計(jì)算的,甚至包括margin-top和margin-bottom height: 50px; margin-top: -25px; }
.box { position:relative; width: 200px; height: 200px; background-color: pink; } .box-center{ position:absolute; top: 0; bottom: 0; margin: auto 0; height: 100px; background-color: greenyellow; }
水平垂直居中
.box { display: flex; width: 100px; height: 100px; background-color: pink; } .box-center{ margin: auto; background-color: greenyellow; } ```css - Flex布局 ```css .box { display: flex; width: 100px; height: 100px; background-color: pink; justify-content: center; align-items: center; } .box-center{ background-color: greenyellow; }
.box { position: relative; height: 100px; width: 100px; background-color: pink; } .box-center{ position: absolute; left: 0; right: 0; bottom: 0; top: 0; margin: auto; width: 50px; height: 50px; background-color: greenyellow; }
用過(guò)Flex么,能簡(jiǎn)單介紹一下么
小提示:如果在項(xiàng)目中使用過(guò),可簡(jiǎn)單介紹一下自己使用Flex解決過(guò)什么問(wèn)題,這里我在項(xiàng)目中印象比較深刻的是使用Flex解決上面內(nèi)容高度不固定,下面內(nèi)容高度自動(dòng)撐滿(mǎn)父容器剩余高度的問(wèn)題。
如果不是很清楚Flex,可以查看阮一峰的文章Flex 布局教程:語(yǔ)法篇。面試官追問(wèn),那么除了Flex,你還知道Grid么?這個(gè)由于兼容性問(wèn)題,我一直沒(méi)有好好研究過(guò),這里可查看阮一峰的文章CSS Grid網(wǎng)格布局教程。
bind的源碼實(shí)現(xiàn)
小提示:這里我回答使用函數(shù)柯里化加上apply或者call可實(shí)現(xiàn)bind,面試官追問(wèn)了一些具體的實(shí)現(xiàn)細(xì)節(jié)。
后來(lái)我自己粗糙的實(shí)現(xiàn)了一下,僅供參考:
Function.prototype.myCall=function (obj) { obj.fn=thislet args=[...arguments].splice(1) let result=obj.fn(...args) delete obj.fn return result } Function.prototype.myApply=function (obj) { obj.fn=thislet args=arguments[1] let result if (args) { result=obj.fn(...args) } else { result=obj.fn() } delete obj.fn return result } Function.prototype.myBind=function (obj) { let context=obj || windowlet _this=thislet _args=[...arguments].splice(1) returnfunction () { let args=arguments// 產(chǎn)生副作用// return obj.fn(..._args, ...args)return _this.apply(context, [..._args, ...args]) } } functionmyFun (argumentA, argumentB) { console.log(this.value) console.log(argumentA) console.log(argumentB) returnthis.value } let obj={ value: 'ziyi2' } console.log(myFun.myCall(obj, 11, 22)) console.log(myFun.myApply(obj, [11, 22])) console.log(myFun.myBind(obj, 33)(11, 22))
偽類(lèi)和偽元素的區(qū)別
小提示:這個(gè)問(wèn)題我當(dāng)時(shí)懵了一下,一下子沒(méi)反應(yīng)過(guò)來(lái)面試官想要問(wèn)什么,就答了這兩者在CSS優(yōu)先級(jí)上有區(qū)別,然后由于遇到不會(huì)的問(wèn)題有些緊張就多說(shuō)了一些廢話(huà),但顯然這不是面試官想要的答案并且消耗了面試官面試的耐心,說(shuō)他問(wèn)的不是這個(gè)。這里再次提示大家,如果你感覺(jué)你說(shuō)不清楚,但是你又知道一點(diǎn),我建議你說(shuō)不知道,不要糾結(jié),面試官不會(huì)因?yàn)槟悴恢酪粋€(gè)問(wèn)題就PASS你,相反你說(shuō)了一些無(wú)關(guān)緊要的廢話(huà),反而在消耗面試官的耐性,增加負(fù)面印象。
偽類(lèi)和偽元素是用來(lái)修飾不在文檔樹(shù)中的部分,比如,一句話(huà)中的第一個(gè)字母,或者是列表中的第一個(gè)元素。下面分別對(duì)偽類(lèi)和偽元素進(jìn)行解釋?zhuān)?/p>
偽類(lèi)用于當(dāng)已有元素處于的某個(gè)狀態(tài)時(shí),為其添加對(duì)應(yīng)的樣式,這個(gè)狀態(tài)是根據(jù)用戶(hù)行為而動(dòng)態(tài)變化的。比如說(shuō),當(dāng)用戶(hù)懸停在指定的元素時(shí),我們可以通過(guò):hover來(lái)描述這個(gè)元素的狀態(tài)。雖然它和普通的css類(lèi)相似,可以為已有的元素添加樣式,但是它只有處于dom樹(shù)無(wú)法描述的狀態(tài)下才能為元素添加樣式,所以將其稱(chēng)為偽類(lèi)。
偽元素用于創(chuàng)建一些不在文檔樹(shù)中的元素,并為其添加樣式。比如說(shuō),我們可以通過(guò):before來(lái)在一個(gè)元素前增加一些文本,并為這些文本添加樣式。雖然用戶(hù)可以看到這些文本,但是這些文本實(shí)際上不在文檔樹(shù)中。
區(qū)別
偽類(lèi)的操作對(duì)象是文檔樹(shù)中已有的元素,而偽元素則創(chuàng)建了一個(gè)文檔樹(shù)外的元素。因此,偽類(lèi)與偽元素的區(qū)別在于:有沒(méi)有創(chuàng)建一個(gè)文檔樹(shù)之外的元素。
CSS3規(guī)范中的要求使用雙冒號(hào)(::)表示偽元素,以此來(lái)區(qū)分偽元素和偽類(lèi),比如::before和::after等偽元素使用雙冒號(hào)(::),:hover和:active等偽類(lèi)使用單冒號(hào)(:)。除了一些低于IE8版本的瀏覽器外,大部分瀏覽器都支持偽元素的雙冒號(hào)(::)表示方法。
小結(jié)
對(duì)于滴滴的這次面試,我感覺(jué)到自己準(zhǔn)備的不是很充分,尤其是自己簡(jiǎn)歷上的項(xiàng)目技術(shù)Graphql。同時(shí)對(duì)于自己不會(huì)的題目強(qiáng)行做了一些解釋說(shuō)明,其實(shí)應(yīng)該簡(jiǎn)潔明了的告訴面試官不會(huì)。
51信用卡(一面)
說(shuō)說(shuō)DOM事件流
在ES5中如何實(shí)現(xiàn)繼承
小提示:這里我說(shuō)了很多,從借用構(gòu)造函數(shù)到組合繼承到寄生組合繼承,但面試官其實(shí)最想聽(tīng)到的是寄生組合繼承。面試官還追問(wèn)我具體要如何實(shí)現(xiàn)寄生組合繼承。當(dāng)然這里其實(shí)問(wèn)的問(wèn)題還可以很多,比如ES6的類(lèi)繼承和ES5中的繼承有什么區(qū)別。
如果對(duì)于繼承以及繼承的區(qū)別不是很清楚的,可以隨便看看我之前寫(xiě)的大筆記js類(lèi)和繼承。
絕對(duì)定位
小提示:這個(gè)建議大家好好回憶一下,例如子元素是相對(duì)父元素的padding、border還是content進(jìn)行定位之類(lèi)的,當(dāng)時(shí)面試官問(wèn)的就這么細(xì)。
消抖和節(jié)流
小提示:面試官只是問(wèn)了一下具體的使用場(chǎng)景,沒(méi)有問(wèn)實(shí)現(xiàn)原理。
簡(jiǎn)單消抖
functiondebounce (fn, wait=1000) { let timeOutId returnfunction () { let context=thisif (timeOutId) { clearTimeout(timeOutId) } timeOutId=setTimeout(()=> { fn.apply(context, arguments) }, wait) } }
帶立即執(zhí)行參數(shù)的消抖
functiondebounceImmediate (fn, wait=1000, immediate) { let timeOutId, context, args const later=(immediate)=> setTimeout(()=> { if (!immediate) { fn.apply(context, args) timeOutId=context=args=null } }, wait) returnfunction () { if (!timeOutId) { timeOutId=later(true) if (immediate) { fn.apply(this, arguments) } context=this args=arguments } else { clearTimeout(timeOutId) timeOutId=later(false) } } }
節(jié)流
functionthrottle (fn, wait) { let timeoutId=nullreturnfunction () { let context=thisif (!timeoutId) { timeoutId=setTimeout(()=> { fn.apply(context, arguments) timeoutId=null }, wait) } } }
Vue中的computed實(shí)現(xiàn)原理
小提示:這個(gè)問(wèn)題面試官問(wèn)的很細(xì),絕對(duì)是想問(wèn)你是否閱讀過(guò)源碼。他首先問(wèn)computed的實(shí)現(xiàn)原理,其次問(wèn)了這樣一個(gè)問(wèn)題:現(xiàn)在有兩個(gè)computed計(jì)算值,其中一個(gè)computed計(jì)算值為什么可以依賴(lài)另外一個(gè)computed計(jì)算值。這里順便將watch的實(shí)現(xiàn)原理也貼上。
watch的實(shí)現(xiàn)原理
watch的分類(lèi):
watch實(shí)現(xiàn)過(guò)程:
computed運(yùn)行原理
var vm=new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar' }, computed: { fullName: function () { returnthis.firstName + ' ' + this.lastName } } })
由于 this.firstName 和 this.lastName (上面是Vue官方示例)都是響應(yīng)式變量,因此會(huì)觸發(fā)它們的 getter,根據(jù)我們之前的分析,它們會(huì)把自身持有的 dep 添加到當(dāng)前正在計(jì)算的 watcher 中,這個(gè)時(shí)候Dep.target就是這個(gè) computed watcher,具體步驟如下:
通過(guò)以上的分析,我們知道計(jì)算屬性本質(zhì)上就是一個(gè) computed watcher,也了解了它的創(chuàng)建過(guò)程和被訪問(wèn)觸發(fā) getter 以及依賴(lài)更新的過(guò)程,其實(shí)這是最新的計(jì)算屬性的實(shí)現(xiàn),之所以這么設(shè)計(jì)是因?yàn)?Vue 想確保不僅僅是計(jì)算屬性依賴(lài)的值發(fā)生變化,而是當(dāng)計(jì)算屬性最終計(jì)算的值發(fā)生變化才會(huì)觸發(fā)渲染 watcher 重新渲染,本質(zhì)上是一種優(yōu)化。
computed計(jì)算值為什么還可以依賴(lài)另外一個(gè)computed計(jì)算值
小提示:這個(gè)問(wèn)題當(dāng)時(shí)完全不知道,哎,官方源碼的套路太深了......
這里希望有大神可以補(bǔ)充說(shuō)明一下。
周期函數(shù)有哪些(beforeCreated和created中間都做了什么
)
初始化 data、props、computed、watcher、provide。官方源碼具體位置src/core/instance/init.js:
callHook(vm, 'beforeCreate') initInjections(vm) // resolve injections before data/props initState(vm) initProvide(vm) // resolve provide after data/props callHook(vm, 'created')
小結(jié)
51信用卡的這次面試其實(shí)面試官考察的點(diǎn)還是蠻深入的,問(wèn)了一些Vue底層源碼的實(shí)現(xiàn),總體感覺(jué)自己回答的還可以,但是面試官說(shuō):你應(yīng)該去阿里...
阿里部門(mén)未知(一面)
說(shuō)說(shuō)Webpack的實(shí)現(xiàn)原理
小提示:這個(gè)直接回答不知道,問(wèn)題較大,我這里猜測(cè)一下是類(lèi)似Babel和AST抽象語(yǔ)法樹(shù)相關(guān),有空去看下源碼。
這個(gè)問(wèn)題希望同學(xué)可以補(bǔ)充一下。
首屏優(yōu)化有哪些解決方案
小提示:這個(gè)問(wèn)題在回答懶加載的過(guò)程中,面試官追問(wèn)懶加載的Webpack配置,我說(shuō)了和代碼切割相關(guān)。
關(guān)于懶加載,這里推薦一篇非常好的文章:Webpack 大法之 Code Splitting。
Node.js的加載機(jī)制(require和module.exports)
小提示:這個(gè)問(wèn)題其實(shí)是非常常見(jiàn)的問(wèn)題,建議大家閱讀一下源碼,有些也可能會(huì)問(wèn)一下比較簡(jiǎn)單的問(wèn)題,例如module.exports和exports的區(qū)別,或者也可能問(wèn)CommonJS引入和ES6引入的區(qū)別。
你覺(jué)得你最擅長(zhǎng)什么
小提示:這個(gè)問(wèn)題是個(gè)大坑阿,我這里直接回答我什么都不擅長(zhǎng),這樣回答顯然面試官是不會(huì)不滿(mǎn)意的,建議大家在面試前好好想想自己到底擅長(zhǎng)啥。
React和Vue的區(qū)別
小提示:這里React真的好久沒(méi)用了,幾乎忘記了,大致說(shuō)了下單向數(shù)據(jù)流、雙向數(shù)據(jù)綁定、數(shù)據(jù)監(jiān)聽(tīng)方式、JSX以及Vue的單文件組件、函數(shù)式編程、Vue的指令之類(lèi)的。
這個(gè)問(wèn)題希望同時(shí)熟悉React和Vue的同學(xué)可以補(bǔ)充一下。
React、Vue和JQuery在什么場(chǎng)景下怎么選型
這個(gè)問(wèn)題希望同學(xué)可以補(bǔ)充一下。
Vue的響應(yīng)式原理
什么情況下會(huì)阻塞DOM渲染
小提示:面試官這里應(yīng)該想問(wèn)DOM渲染的過(guò)程中可能有哪些情況會(huì)阻塞渲染。我當(dāng)時(shí)回答不知道。
這個(gè)問(wèn)題希望同學(xué)可以補(bǔ)充一下。
有哪些異步函數(shù)
小提示:回答了宏任務(wù)和微任務(wù)。
講講MVVM,說(shuō)說(shuō)與MVC有什么區(qū)別
小提示:這個(gè)問(wèn)題我專(zhuān)門(mén)發(fā)了一篇掘金文章,但是很多人好像都不是很感興趣的樣子,但是面試官真的就問(wèn)了這樣一個(gè)問(wèn)題。
這里推薦我之前寫(xiě)的掘金文章基于Vue實(shí)現(xiàn)一個(gè)簡(jiǎn)易MVVM/MV*設(shè)計(jì)模式的演變歷史,一開(kāi)始重點(diǎn)講解了MVC、MVP以及MVVM的演變過(guò)程和區(qū)別。
阿里CBU技術(shù)部(一面)
說(shuō)說(shuō)z-index有什么需要注意的地方
小提示:真的忘記的差不多了,就簡(jiǎn)單說(shuō)了只能在同一層疊上下文中進(jìn)行z-index值比較、和絕對(duì)定位的關(guān)系,z-index值不需要設(shè)置過(guò)大,只需要理清楚層級(jí)關(guān)系即可。面試官追問(wèn)了z-index值和background的覆蓋關(guān)系,還追問(wèn)了絕對(duì)定位元素以及后來(lái)居上的準(zhǔn)則。面試官還問(wèn)了z-index默認(rèn)值是什么,0和auto有沒(méi)有區(qū)別?真的對(duì)于CSS可能平常就用的不多,所以這個(gè)問(wèn)題答的不是很好。
可能面試官最想知道的是下面這張圖:
這里附上張?chǎng)涡竦奈恼律钊肜斫釩SS中的層疊上下文和層疊順序。
這里由于回答了定位,面試官追問(wèn)固定定位的元素是相對(duì)于什么進(jìn)行定位?相對(duì)定位會(huì)脫離正常文檔流么?絕對(duì)定位是相對(duì)于什么元素進(jìn)行定位?
熟悉CSS3動(dòng)畫(huà)么
小提示:CSS3動(dòng)畫(huà)硬件加速?CSS3動(dòng)畫(huà)的性能問(wèn)題(重繪和重流,是否需要脫離正常文檔流)?這個(gè)我當(dāng)時(shí)答不知道,確實(shí)平常用的很少,如果熟悉Vue過(guò)渡動(dòng)畫(huà)的同學(xué)可以講講過(guò)渡動(dòng)畫(huà)?
有沒(méi)有做過(guò)什么可視化的項(xiàng)目
小提示:我的回答:地圖算么?基于OpenLayers設(shè)計(jì)過(guò)地圖的Vue組件庫(kù)。
對(duì)于可視化希望同學(xué)可以補(bǔ)充一下。
你覺(jué)得你最擅長(zhǎng)的是什么
小提示:這個(gè)問(wèn)題簡(jiǎn)直就是給人挖坑。
Flex實(shí)現(xiàn)兩列布局
這里簡(jiǎn)單實(shí)現(xiàn)一下(其實(shí)應(yīng)該使用flex-basis屬性):
<divclass="box"><divclass="box-left"></div><divclass="box-right"></div></div> .box { height: 200px; display: flex; } .box > div { height: 100%; } .box-left { width: 200px; background-color: blue; } .box-right { flex: 1; // 設(shè)置flex-grow屬性為1,默認(rèn)為0 overflow: hidden; background-color: red; }
ES6/ES7/ES8的特性
說(shuō)說(shuō)DOM事件流
小提示:面試官追問(wèn)事件委托有什么優(yōu)點(diǎn)(起碼兩個(gè)以上)、target/currentTarget/relateTarget具體指向什么目標(biāo)。
你覺(jué)得你有做過(guò)推動(dòng)流程或者改善流程的事件么,舉例說(shuō)明
小提示:這個(gè)如果做過(guò)什么規(guī)范或者開(kāi)發(fā)工具之類(lèi)的,應(yīng)該比較好回答。
小結(jié)
總體來(lái)說(shuō)這次面試面得很細(xì),有些知識(shí)點(diǎn)已經(jīng)忘記,建議大家面試前把一些感覺(jué)不是很熟悉的原生知識(shí)點(diǎn)回憶起來(lái),尤其是在開(kāi)發(fā)中都不怎么會(huì)使用一些CSS樣式設(shè)計(jì)的童鞋(現(xiàn)在很多都是組件庫(kù)的設(shè)計(jì)方案,樣式早已經(jīng)封裝掉了)。
阿里企業(yè)智能事業(yè)部(一面)
Event Loop
Webpack的loader和plugins的區(qū)別
小提示:當(dāng)時(shí)直接回答不知道,確實(shí)Webpack我只會(huì)用,還沒(méi)了解過(guò)內(nèi)部的實(shí)現(xiàn)原理和構(gòu)成。這個(gè)后續(xù)無(wú)論如何都要好好理解一下原理。
這個(gè)問(wèn)題希望同學(xué)可以補(bǔ)充一下。
HTTP狀態(tài)碼206是干什么的
小提示:工作中沒(méi)有遇到過(guò)需要上傳下載大型文件,所以這個(gè)問(wèn)題當(dāng)時(shí)老老實(shí)實(shí)回答不知道。具體應(yīng)該和斷點(diǎn)續(xù)傳相關(guān),可能也需要回答一些range的頭部信息等。
React高階組件的作用有哪些
小提示:好久沒(méi)用過(guò)React了,大致只知道Racct是單向數(shù)據(jù)流的,利用高階組件可以實(shí)現(xiàn)類(lèi)似于Vue的雙向數(shù)據(jù)綁定。
這個(gè)問(wèn)題希望同學(xué)可以補(bǔ)充一下。
React和Vue的區(qū)別
Service Worker有哪些作用
小提示:當(dāng)時(shí)怕說(shuō)錯(cuò),老老實(shí)實(shí)回答不知道。后來(lái)查了一下應(yīng)該和緩存以及HTTP請(qǐng)求攔截相關(guān)。
這個(gè)問(wèn)題希望同學(xué)可以補(bǔ)充一下。
跨域
文件上傳的二進(jìn)制具體是怎么處理的
小提示:只知道上傳的頭信息是application/x-www-form-urlencoded,也可以對(duì)上傳的文件的數(shù)據(jù)進(jìn)行攔截處理,例如對(duì)上傳文件的信息進(jìn)行加密處理。
這個(gè)問(wèn)題希望同學(xué)可以補(bǔ)充一下。
Vue響應(yīng)式原理
首屏加載性能優(yōu)化
小結(jié)
其實(shí)這一次面試自己感覺(jué)面試的不是很好(盡管面試官問(wèn)的確實(shí)比我上面列出的問(wèn)題多),因?yàn)橛泻脦讉€(gè)問(wèn)題自己確實(shí)不清楚。這里再次建議大家不知道就是回答不知道,這樣不會(huì)對(duì)面試官造成一些負(fù)面印象。這一次面試能夠通過(guò)運(yùn)氣占了很大一部分。
阿里企業(yè)智能事業(yè)部(二面)
computed的實(shí)現(xiàn)原理
Vue的整個(gè)實(shí)現(xiàn)原理
小提示:當(dāng)時(shí)面試官問(wèn)的蠻好玩的,他問(wèn)從開(kāi)始寫(xiě)一個(gè).vue文件開(kāi)始到DOM渲染到頁(yè)面上,Vue做了哪些工作。然后我當(dāng)時(shí)沒(méi)理解面試官是要問(wèn)vue-loader?DOM樹(shù)的渲染過(guò)程?來(lái)來(lái)回回試探性的問(wèn)了面試官幾次,才理解原來(lái)面試官想知道Vue源碼的整個(gè)實(shí)現(xiàn)過(guò)程。
大家如果想了解Vue源碼實(shí)現(xiàn)的整個(gè)粗略過(guò)程,可以看下之前寫(xiě)的文章基于Vue實(shí)現(xiàn)一個(gè)簡(jiǎn)易MVVM/Vue的運(yùn)行機(jī)制簡(jiǎn)述。
通訊
小提示:由于這邊涉及到一些??档脑O(shè)備(上下位機(jī)通信),面試官問(wèn)我如何知道上位機(jī)軟件給下位機(jī)設(shè)備發(fā)送了5次信息。這個(gè)其實(shí)大部分Web前端開(kāi)發(fā)在工作上很難遇到類(lèi)似的問(wèn)題,辛虧我以前畢業(yè)設(shè)計(jì)中做過(guò)上下位機(jī)的TCP通訊。后來(lái)我從Leader面那里了解到二面面試官應(yīng)該是做iot物聯(lián)網(wǎng)開(kāi)發(fā)這一塊的。
請(qǐng)求幀數(shù)據(jù)結(jié)構(gòu)如下:
Chrome插件如何屏蔽廣告
小提示:這個(gè)問(wèn)題當(dāng)時(shí)回答不知道,其實(shí)后面想想最簡(jiǎn)單的辦法是先找出廣告元素的一些通用特性,然后在Chrome插件中通過(guò)注入腳本的形式將這些廣告元素隱藏掉。
這里不知道有沒(méi)有更好的其他方式,例如不知道Service Work對(duì)請(qǐng)求攔截處理是否可以有效屏蔽廣告等,這個(gè)問(wèn)題希望同學(xué)可以補(bǔ)充一下。
如何判斷兩個(gè)變量相等
小提示:這里需要分基本類(lèi)型和引用類(lèi)型,面試官在這里具體想問(wèn)的是Object.is的實(shí)現(xiàn)原理。這是面試官問(wèn)我的第一個(gè)問(wèn)題,當(dāng)時(shí)直接回答不知道,內(nèi)心都覺(jué)得接下來(lái)要涼涼了。
Watch的運(yùn)行原理
Vue的數(shù)據(jù)為什么頻繁變化但只會(huì)更新一次
小提示:這里問(wèn)的是Vue源碼對(duì)于視圖更新的優(yōu)化。我這里的回答是亂糟糟的,希望有同學(xué)能夠給出一個(gè)精準(zhǔn)并且簡(jiǎn)短的回答。
Vue 異步執(zhí)行 DOM 更新。只要觀察到數(shù)據(jù)變化,Vue 將開(kāi)啟一個(gè)隊(duì)列,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)改變。如果同一個(gè) watcher 被多次觸發(fā),只會(huì)被推入到隊(duì)列中一次。這種在緩沖時(shí)去除重復(fù)數(shù)據(jù)對(duì)于避免不必要的計(jì)算和 DOM 操作上非常重要。然后,在下一個(gè)的事件循環(huán)“tick”中,Vue 刷新隊(duì)列并執(zhí)行實(shí)際 (已去重的) 工作。Vue 在內(nèi)部嘗試對(duì)異步隊(duì)列使用原生的 Promise.then 和 MessageChannel,如果執(zhí)行環(huán)境不支持,會(huì)采用 setTimeout(fn, 0) 代替。
另外,關(guān)于waiting變量,這是很重要的一個(gè)標(biāo)志位,它保證flushSchedulerQueue回調(diào)($nextTick中執(zhí)行)允許被置入callbacks一次。
因?yàn)閂ue的事件機(jī)制是通過(guò)事件隊(duì)列來(lái)調(diào)度執(zhí)行,會(huì)等主進(jìn)程執(zhí)行空閑后進(jìn)行調(diào)度,所以先會(huì)去等待所有的同步代碼執(zhí)行完成之后再去一次更新。這樣的性能優(yōu)勢(shì)很明顯,比如:
現(xiàn)在有這樣的一種情況,mounted的時(shí)候test的值會(huì)被循環(huán)執(zhí)行++1000次。每次++時(shí),都會(huì)根據(jù)響應(yīng)式觸發(fā)setter->Dep->Watcher->update->run。如果這時(shí)候沒(méi)有異步更新視圖,那么每次++都會(huì)直接操作DOM更新視圖,這是非常消耗性能的。所以Vue實(shí)現(xiàn)了一個(gè)queue隊(duì)列,在下一個(gè)tick(或者是當(dāng)前tick的微任務(wù)階段)統(tǒng)一執(zhí)行queue中Watcher的run。同時(shí),擁有相同id的Watcher不會(huì)被重復(fù)加入到該queue中去,所以不會(huì)執(zhí)行1000次Watcher的run。最終更新視圖只會(huì)直接將test對(duì)的DOM的0變成1000。保證更新視圖操作DOM的動(dòng)作是在當(dāng)前棧執(zhí)行完以后下一個(gè)tick(或者是當(dāng)前tick的微任務(wù)階段)的時(shí)候調(diào)用,大大優(yōu)化了性能。
執(zhí)行順序update -> queueWatcher -> 維護(hù)觀察者隊(duì)列(重復(fù)id的Watcher處理) -> waiting標(biāo)志位處理(保證需要更新DOM或者Watcher視圖更新的方法flushSchedulerQueue只會(huì)被推入異步執(zhí)行的$nextTick回調(diào)數(shù)組一次) -> 處理$nextTick(在為微任務(wù)或者宏任務(wù)中異步更新DOM)->
由于VUE的數(shù)據(jù)驅(qū)動(dòng)視圖更新是異步的,即修改數(shù)據(jù)的當(dāng)下,視圖不會(huì)立刻更新,而是等同一事件循環(huán)中的所有數(shù)據(jù)變化完成之后,再統(tǒng)一進(jìn)行視圖更新。在同一事件循環(huán)中的數(shù)據(jù)變化后,DOM完成更新,立即執(zhí)行nextTick(callback)內(nèi)的回調(diào)。
vue和react一樣,對(duì)dom的修改都是異步的。它會(huì)在隊(duì)列里記錄你對(duì)dom的操作并進(jìn)行diff操作,后一個(gè)操作會(huì)覆蓋前一個(gè),然后更新dom。
Event Loop
除了Flex還可以用什么進(jìn)行布局
小提示:我猜這里面試官想問(wèn)的是Grid,當(dāng)時(shí)說(shuō)不知道。
絕對(duì)定位、固定定位和z-index
小提示:感謝CBU技術(shù)部的面試官。
絕對(duì)定位
屬性介紹
浮動(dòng)、絕對(duì)定位和固定定位會(huì)脫離文檔流,相對(duì)定位不會(huì)脫離文檔流,絕對(duì)定位相對(duì)于該元素最近的已定位的祖先元素,如果沒(méi)有一個(gè)祖先元素設(shè)置定位,那么參照物是body層。
絕對(duì)定位相對(duì)于包含塊的起始位置:
問(wèn)答題:
小結(jié)
這一次面試官問(wèn)我的第一個(gè)問(wèn)題Object.is就沒(méi)答上來(lái),不過(guò)面試官顯然沒(méi)有因?yàn)殚_(kāi)頭答的不好就否定面試者。大家如果在面試時(shí)第一個(gè)問(wèn)題就答不上來(lái),不要慌,要保持良好的心態(tài),把接下來(lái)能答的問(wèn)題好好答上來(lái)??赡芎芏嗤瑢W(xué)會(huì)疑問(wèn),好像還有好幾個(gè)問(wèn)題感覺(jué)沒(méi)答上來(lái),但是可能只要有一個(gè)問(wèn)題答的非常出彩,仍然可以彌補(bǔ)那些沒(méi)答上來(lái)的問(wèn)題(這里面試官當(dāng)時(shí)說(shuō)Vue源碼的實(shí)現(xiàn)過(guò)程我說(shuō)的比較清楚,還沒(méi)有一個(gè)面試者答的比我更清楚的)。
阿里企業(yè)智能事業(yè)部(Leader面)
三面是Leader現(xiàn)場(chǎng)面,我當(dāng)時(shí)特別擔(dān)心有贊二面的情況發(fā)生,冷不丁又給你來(lái)一道算法題,這些真是我最不擅長(zhǎng)的點(diǎn)。因?yàn)橛悬c(diǎn)心虛我就問(wèn)了下在阿里的師兄(師兄可能也做招聘工作,當(dāng)時(shí)還怪我沒(méi)有找他內(nèi)推...),他說(shuō)現(xiàn)場(chǎng)面其實(shí)最主要的是好好準(zhǔn)備簡(jiǎn)歷上的內(nèi)容,面試官一般都會(huì)根據(jù)簡(jiǎn)歷進(jìn)行問(wèn)答,還說(shuō)他當(dāng)時(shí)面試阿里時(shí)會(huì)讓他畫(huà)一些框架層次圖(這個(gè)我當(dāng)時(shí)沒(méi)在意,結(jié)果面試官確實(shí)讓我根據(jù)其中某個(gè)項(xiàng)目畫(huà)一個(gè)框架層次圖)。Leader面的時(shí)候在場(chǎng)的有兩個(gè)面試官和一個(gè)HR。
Leader(一)面試
先是進(jìn)來(lái)一個(gè)氣場(chǎng)很足的Leader,看起來(lái)很權(quán)威,但是問(wèn)問(wèn)題還蠻隨意的,就簡(jiǎn)單的讓我介紹一下自己做的項(xiàng)目,然后翻看了我做的一些東西。感覺(jué)他好像有點(diǎn)心不在焉,翻看的很隨意,我在回答問(wèn)題的時(shí)候用余光關(guān)注了一下大佬的表情,感覺(jué)他在我項(xiàng)目經(jīng)歷那一塊停留了非常長(zhǎng)的時(shí)間。
Leader(二)面試
我正回答著自己的項(xiàng)目經(jīng)歷,Leader二和HR進(jìn)來(lái)了,等我回答完Leader一就讓Leader二開(kāi)始面我。Leader二就問(wèn)了我其中的兩個(gè)項(xiàng)目。問(wèn)我的第一個(gè)項(xiàng)目是自己做的公司內(nèi)部的工具,他問(wèn)這個(gè)平臺(tái)有什么可以衡量的數(shù)據(jù)表明公司內(nèi)部人員的使用情況。我回答當(dāng)時(shí)因?yàn)轭I(lǐng)導(dǎo)覺(jué)得沒(méi)必要做,就沒(méi)有做數(shù)據(jù)統(tǒng)計(jì)這一塊,告訴了他數(shù)據(jù)庫(kù)里的一些真實(shí)數(shù)據(jù)情況。然后他問(wèn)PV、UV應(yīng)該怎么統(tǒng)計(jì)(我當(dāng)時(shí)還厚臉皮的問(wèn)他PV和UV是什么)?如果訪問(wèn)的頁(yè)面出不來(lái)PV怎么統(tǒng)計(jì)?頁(yè)面有沒(méi)有做什么行為監(jiān)測(cè)?頁(yè)面訪問(wèn)量過(guò)大怎么處理?我大致講了一些我的思路。
接著問(wèn)我第二個(gè)項(xiàng)目(Low Code相關(guān)),我就回答了這個(gè)項(xiàng)目的技術(shù)體系,從以前做了什么到現(xiàn)在做到什么程度,到未來(lái)需要做成什么樣,統(tǒng)統(tǒng)仔細(xì)的說(shuō)了一遍。Leader二就問(wèn)我未來(lái)做成什么樣能不能思考一下怎么做,給了我5分鐘的時(shí)間(這期間他一直反復(fù)的在翻閱我的簡(jiǎn)歷)。然后我就假裝思考了5分鐘左右,其實(shí)腦子里一片空白,當(dāng)時(shí)對(duì)于未來(lái)要做成什么樣還只是個(gè)構(gòu)思。然后Leader二還是很體貼的,他說(shuō)你可以在墻上畫(huà)一畫(huà)(墻上可以寫(xiě)字),我就大致畫(huà)了畫(huà),Leader二問(wèn)我能不能畫(huà)一畫(huà)這個(gè)項(xiàng)目的框架層次圖,我就簡(jiǎn)單的畫(huà)了畫(huà)...最后Leader二直接說(shuō)你們做的太Low了,這個(gè)(Low Code)在我們這里已經(jīng)是兩年前的技術(shù)了...(這個(gè)我還是要解釋下,我所在的部門(mén)從開(kāi)始用Vue到目前只有短短的兩年時(shí)間,在這兩年時(shí)間里技術(shù)體系還是飛速的在沉淀和發(fā)展,我離開(kāi)之前已經(jīng)構(gòu)思并實(shí)現(xiàn)了部分Vue技術(shù)棧的Low Code解決方案,如果這方面感興趣的同學(xué)也可以找我溝通)。
Leader二還蠻好玩的,他說(shuō)Low Code如果真的做出來(lái)了,都沒(méi)前端什么事情了,那你干嘛去?順著這個(gè)問(wèn)題他還問(wèn)我未來(lái)的前端應(yīng)該怎么發(fā)展?未來(lái)前端有哪些可以挖掘的點(diǎn)?我回答了一些Graphql、可視化等,我還說(shuō)了一個(gè)特別搞笑的回答,我說(shuō)從以往的發(fā)展來(lái)看,前端應(yīng)該搶占后端的資源,把后端限制我們的事情讓前端也能做,讓前端更加解放。Leader二當(dāng)場(chǎng)就進(jìn)行了反駁,說(shuō)是要有價(jià)值才做,而不是為了能做而做,嚇得我不輕...然后Leader二還詳細(xì)的跟我解釋了未來(lái)發(fā)展這個(gè)問(wèn)題他希望得到什么回答,當(dāng)時(shí)還是覺(jué)得Leader二蠻親切的。
HR面試
Leader二問(wèn)完以后HR就接著問(wèn)我了以下幾個(gè)問(wèn)題:
然后Leader一順著HR問(wèn)了一個(gè)小問(wèn)題:
最后問(wèn)我還有什么想問(wèn)的,我當(dāng)時(shí)已經(jīng)被三個(gè)人問(wèn)的有點(diǎn)迷迷糊糊了,然后想了想說(shuō)沒(méi)有。
小結(jié)
這次現(xiàn)場(chǎng)面其實(shí)我感覺(jué)自己面得不是很好,總感覺(jué)自己要掛了??偣裁媪藢⒔?個(gè)半小時(shí)左右,尤其是Leader二的問(wèn)題很多不是他想要的答案,但是最終居然過(guò)了。智能事業(yè)部(HR面)
企業(yè)智能事業(yè)部Leader面后又收到了HR面的面試通知,這一輪面試大致問(wèn)了以下問(wèn)題:
小提示:這里HR會(huì)問(wèn)的其實(shí)不止這些問(wèn)題,例如你為什么喜歡Web前端這個(gè)崗位、你未來(lái)的職業(yè)規(guī)劃、你覺(jué)得你的優(yōu)點(diǎn)和缺點(diǎn)有哪些、為什么選擇阿里巴巴、對(duì)之前幾個(gè)面試官做下評(píng)價(jià)、你用過(guò)阿里的哪些產(chǎn)品順便談?wù)勥@些產(chǎn)品的優(yōu)缺點(diǎn)、你對(duì)于互聯(lián)網(wǎng)是怎么理解的...
小結(jié)
對(duì)于HR面還是要好好準(zhǔn)備的,尤其是有些問(wèn)題還是很容易挖坑的,例如你為什么離開(kāi)現(xiàn)在的公司(你當(dāng)然不應(yīng)該抱怨現(xiàn)在的公司有哪些不好的地方,更多的應(yīng)該表明自己想要尋找更好的發(fā)展機(jī)會(huì),自己的一些現(xiàn)實(shí)因素,比如對(duì)于我而言是現(xiàn)在應(yīng)聘的公司離自己的家更近,又或者是自己工作到達(dá)了迷茫期,想跳出迷茫期等等),你覺(jué)得你做的最有成就感的一件事(你要是說(shuō)個(gè)簡(jiǎn)單的,HR會(huì)覺(jué)得你工作能力不強(qiáng)),你一般解決問(wèn)題的方法有哪些(HR當(dāng)然也想考察你解決問(wèn)題的能力,你要是說(shuō)什么百度啊之類(lèi)的HR當(dāng)然會(huì)覺(jué)得你解決問(wèn)題的能力不強(qiáng)),你期望的薪資待遇是多少(你要是不喜歡這家公司,可以期望高一些,你要是很喜歡這家公司面試過(guò)程很愉快上浮個(gè)30%左右,面試過(guò)程一般上浮個(gè)20%左右)。
性是HTML元素提供的附國(guó)信息
HTML元素可以設(shè)置屬性
屬性可以在元素中添加附加信息
屬性一般描述于開(kāi)始標(biāo)簽
屬性總是以名稱(chēng)/值對(duì)應(yīng)的形式出現(xiàn),例如:name="value"
例,鏈接地址是href的屬性
<a >鏈接地址是href的屬性</a>
HTML屬性常用引用屬性值
屬性值應(yīng)該始終被包含在引號(hào)內(nèi)
雙引號(hào)是常用的,單引號(hào)也沒(méi)有問(wèn)題,
如果屬性值本身就包含了雙引號(hào),即么則必須引用單引號(hào),例:name='John"ShotGun"Nelson'
HTML提示:使用小寫(xiě)屬性
屬性和屬性值對(duì)大小寫(xiě)不敏感。
HTML屬性參考
calss 為HMTL元素定義一個(gè)或多個(gè)名
id 定義元素的唯一id
style 規(guī)定元素的行內(nèi)樣式
title 描述元素的額外信息
HTML標(biāo)題
HTML注釋
類(lèi)似于對(duì)代碼進(jìn)行備注,默認(rèn)有兩種試
1、<!-- 這是一個(gè)小的注釋 -->
常用于一小段注釋
2、//注釋 有時(shí)候不起作用,不知道為啥,知道的回復(fù)下啦
HTML提示,如何查看源代碼
如果你想看,在網(wǎng)頁(yè)中,單擊右鍵,然后選擇查看“源文件”或者醒看頁(yè)面源代碼即可;
TML 基礎(chǔ)
非常簡(jiǎn)單的HTML文檔
HTML 標(biāo)題
HTML 段落
HTML 鏈接
HTML 圖片
實(shí)例解析
HTML 標(biāo)題
HTML 標(biāo)題
在html源碼中插入注釋
插入水平線
實(shí)例解析
HTML 段落
HTML 段落
更多段落
本例演示在 HTML 文檔中折行的使用。
HTML 格式化的某些問(wèn)題。
實(shí)例解析
HTML 文本格式化
文本格式化
此例演示如何使用 pre 標(biāo)簽對(duì)空行和空格進(jìn)行控制。
此例演示不同的"計(jì)算機(jī)輸出"標(biāo)簽的顯示效果。
此例演示如何在 HTML 文件中寫(xiě)地址。
此例演示如何實(shí)現(xiàn)縮寫(xiě)或首字母縮寫(xiě)。
此例演示如何改變文字的方向。
此例演示如何實(shí)現(xiàn)長(zhǎng)短不一的引用語(yǔ)。
文本下劃線與刪除線
實(shí)例解析
HTML 樣式
HTML Style 元素
背景色樣式
字體樣式,顏色,大小
文本對(duì)齊樣式
設(shè)置文本字體
設(shè)置文本字體大小
設(shè)置文本字體顏色
設(shè)置文本字體,字體大小,字體顏色
HTML使用不同樣式
沒(méi)有下劃線的鏈接
鏈接到一個(gè)外部樣式表
實(shí)例解析
HTML 鏈接
創(chuàng)建超級(jí)鏈接
將圖像作為鏈接
在新的瀏覽器窗口打開(kāi)鏈接
鏈接到同一個(gè)頁(yè)面的不同位置
跳出框架
創(chuàng)建電子郵件鏈接
創(chuàng)建電子郵件鏈接 2
實(shí)例解析
HTML 圖像
插入圖像
從不同的位置插入圖片
排列圖片
本例演示如何使圖片浮動(dòng)至段落的左邊或右邊。
制作圖像鏈接
創(chuàng)建圖像映射
實(shí)例解析
HTML 表格
簡(jiǎn)單的表格
沒(méi)有邊框的表格
表格中的表頭
帶有標(biāo)題的表格
跨行或跨列的表格單元格
表格內(nèi)的標(biāo)簽
單元格邊距(Cell padding)
單元格間距(Cell spacing)
實(shí)例解析
HTML 列表
無(wú)序列表
有序列表
不同類(lèi)型的有序列表
不同類(lèi)型的無(wú)序列表
嵌套列表
嵌套列表 2
定義列表
實(shí)例解析
HTML Forms 和 Input
創(chuàng)建文本域(Text fields)
創(chuàng)建密碼域
復(fù)選框
單選按鈕
簡(jiǎn)單的下拉列表
預(yù)選下拉列表
本例演示如何創(chuàng)建一個(gè)文本域(多行文本輸入控件)。
創(chuàng)建一個(gè)按鈕
本例演示如何在數(shù)據(jù)周?chē)L制一個(gè)帶標(biāo)題的框。
帶有文本域與輸入域的表單
帶有復(fù)選框與提交按鈕的form表單
帶有單選框與提交按鈕的表單
發(fā)送郵件表單
實(shí)例解析
HTML iframe
內(nèi)聯(lián)框架 (HTML頁(yè)面中插入框架)
實(shí)例解析
HTML 頭部元素
描述了文檔標(biāo)題
HTML頁(yè)面中默認(rèn)的URL鏈接
提供文檔元數(shù)據(jù)
實(shí)例解析
HTML 腳本
插入一個(gè)腳本
使用 <noscript> 標(biāo)簽
實(shí)例解析
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。