近段時間看了不少的前端面試題,很多大牛也對此做了整理。這篇文就算是借花獻佛啦。總體來說基本上每家問的問題也差不多,可能不同業務的公司問的問題的側重點也不太一樣,有的側重於移動端適配CSS布局瀏覽器兼容IE hack,而有的側重於JS邏輯面向對象設計模式考察等。可能將實際工作中會遇到的問題的場景,以及各種技術的坑作為面試題,這樣一則可以看出他的經驗多少,二則也可以防止他做筆試題的時候手機搜索結果。
【手寫事件模型及事件代理/委托】
這個算是被問到的最多次數的問題了,首先要求描述下js里面的“事件的三個階段”,如果沒有聽說過三個階段,那基本上就沒戲了。分別是捕獲,目標,冒泡階段,低版本IE不支持捕獲階段。然后可能問到IE和W3C不同綁定事件解綁事件的方法有什么區別,參數是什么,以及事件對象e有什么區別等等。
如果上述都沒問題,接下來可能會問“事件的代理/委托”的原理以及優缺點,這是靠事件的冒泡機制來實現的,優點是
1、可以大量節省內存占用,減少事件注冊,比如在table上代理所有td的click事件就非常棒
2、可以實現當新增子對象時無需再次對其綁定事件,對於動態內容部分尤為合適
事件代理的應用常用應該僅限於上述需求下,如果把所有事件都用代理就可能會出現事件誤判,即本不應用觸發事件的都被綁上了事件,事實上如果有人把頁面里的所有事件都綁定到document用委托的,這是極不明智的做法。“所謂酒勁雖好,可不要貪杯喲~”
之后對方可能要求你手寫原生js實現事件代理,並要求兼容瀏覽器,其實就是考核對事件對象e的了解程度,以及在IE下對應的屬性名。其實此時如果你說就是用target,currentTarget,以及IE下的srcElement和this,基本上就可以略過了。
如果上述都OK的話,那么極有可能要求你實現事件模型,即寫一個類或是一個模塊,有兩個函數,一個bind一個trigger,分別實現綁定事件和觸發事件,核心需求就是可以對某一個事件名稱綁定多個事件響應函數,然后觸發這個事件名稱時,依次按綁定順序觸發相應的響應函數。
這個需求如果對於做過C#的人來說就再熟悉不過了,他根本就是C#中的“委托"(delegate)。而委托與事件幾乎是一家子。回到前面說的題目,大致實現思路就是創建一個類或者匿名函數,在bind和trigger函數外層作用於創建一個字典對象,用於存儲注冊的事件及響應函數列表,bind時,如果字典沒有則創建一個,key是事件名稱,value是數組,里面放着當前注冊的響應函數,如果字段中有,那么就直接push到數組即可。trigger時調出來依次觸發事件響應函數即可。
不過還有很多細節,比如說觸發響應函數時的上下文應該是什么,觸發響應函數的參數列表應該是什么,如果要求把調用trigger的參數列表都傳到響應函數中還要考慮到arguments對象轉化為純數組才行等等。還有一些面試官會追問道事件如何派發也就是事件廣播(dispatchEvent)等等,這里不再展開。有關事件的考核點大概也就這么多了。
【前端性能優化】
這個簡直老生常談,不管是園子里還是園子外,關於前端優化的東西太多太多了,不同角度不同方向也有很多,網絡性能優化,加快訪問速度,瀏覽器並行加載數量,怎樣實現原生JS異步載入,CDN加載的原理,如何將不同靜態資源發布到多個域名服務器上,發布后這些靜態字段的url路徑該怎么批量改寫,用什么工具進行項目打包,css打包后的相對路徑怎么轉換為絕對路徑,用什么工具進行項目模塊依賴管理,怎么進行cookie優化等等。
這個說起來就很多了,盡可能的按照自己做過的優化來講,否則面試官隨便挑一項深究都可能會卡殼,與其這樣還不如不講。
【閉包原理及應用】
這個問題的經典性,幾乎所有面試官都會問到這個問題,什么情況下會發生閉包,為什么需要閉包,什么場景下需要,閉包閉了誰,怎么釋放被閉包的變量內存,閉包的優點是什么,缺點是什么等。
關於閉包,有的是上述提問,有的是直接做閉包面試題。關於概念網上一搜一大把,關於閉包面試題(之后盡量補上)。
【手寫Function.bind函數】
首先會要求解釋下這個函數的作用,以及在什么場景下需要用到它,最后手寫一個Function.bind函數。
只要掌握核心幾點就沒有問題:
1、Function.bind 返回的也是一個函數,所以注定發生了閉包
2、在返回的這個函數中去調用一個其他的函數,這其實本質上就是函數鈎子HOOK
關於在JS里的函數鈎子,我認為只需要維護以下三點即可:
1、保持函數的this指向 2、保持函數的所有參數都傳遞到目標函數 3、保持函數的返回值
有了以上這幾點,這個函數就非常好寫了,下面是MSDN上的標准Polyfill:
1 if(!Function.prototype.bind) { 2 Function.prototype.bind = function (o this) { 3 if(typeof this !== "function") { //closest thing possible to the ECMAScript 5 //internal IsCallable function throw new 4 TypeError("Function.prototype.bind - what is trying to be bound is not callable"); 5 } 6 var aArgs = Array.prototype.slice.call (argumenrs,1), 7 fToBind = this, 8 fNOP = function() {}, 9 fBound = function() { 10 return fToBind,apply(this instanceof fNOP? this:oThis || this, 11 aArgs.concat(Array..prototype.slice.call(arguments))); 12 }; 13 fNOP..prototype = this.prototype; 14 fBound.prototype = new fNOP() ; 15 return fBound; 16 }; 17 }
(手寫數組快速排序/去重)不管排序也好,還是去重也罷,都是計算機基礎知識;對於准備面試的童鞋來講,准備下常用的算法還是比較重要的,大部分公司還是比較看中此類基礎知識的。
【JS的定義提升】
利用js的特性定義提升這個知識點衍生出來的面試題相當之多,諸如以下等等
(function(a) { conole.log(a); var a = 10; function a() {}; }(100))
【跨域】
關於跨域大概可以分iframe的跨域,和純粹的跨全域請求。
關於跨域的可以去園子里看這幾篇文章:
JavaScript跨域總結與解決辦法(《JavaScript跨域總結與解決辦法》)
跨域-知識(http://www.cnblogs.com/scottckt/archive/2011/11)
跨域資源共享的10中方式(http://www.cnblogs.com/cat3/archive/2011/06/15)
其實正統的跨全域的解決方法大致也就 JSONP,Access Control 和服務器代理這三種
【JSONP原理】
只要聊到跨域,就必須聊到JSONP,那么就需要講一下JSONP的實現原理,以及你在項目中哪個需求使用了JSONP,這里簡單講就是HTML里面所有帶src屬性的標簽都可以跨域,如iframe,img,script等。
所以可以把需要跨域的請求改成用script腳本加載即可,服務器返回執行字符串,但是這個字符串實在window全局作用域下執行的,你需要把它返回到你的代碼的作用域內,這里就需要臨時創建一個全局的回調函數,並把它傳到后台,最后再整合實際要請求的數組,返回給前端,讓瀏覽器直接調用,用回調的形式回到你的源代碼流程中。
【將url的查詢參數解析成字典對象】
這個題目不約而同的出現在了多家公司的面試題中,當然也是因為太過典型,解決方案無非就是拆字符串或者用正則匹配來解決,個人強烈建議用正則來匹配,因為url允許用戶隨意輸入,如果用拆字符的方式,有任何一處沒有考慮到容錯,就會導致整個js都報錯。而正則就沒有這個問題,它只配對出正確的配對,非法的全部過濾掉,簡單方便。
1 function getQueryObject(url) { 2 url = url == null ? window.location.href : url; 3 var search = url.substring(url.lastIndexOf("?") + 1); 4 var obj = {}; 5 var reg = /([^?&=]+)=([^?&=]*)/g; 6 search.replace(reg,function(rs, $1, $2) { 7 var name = decodeURLComponent($1); 8 var val = decodeURLComponent($2); 9 var val = String(val); 10 obj[name] = val; 11 return rs; 12 }); 13 return obj; 14 }
(函數節流) 對於常見的場景,如網頁滾動時,經常會有滾動到哪時做什么樣的動畫效果,遂要注冊onscroll事件,如何減少觸發次數,到達優化性能,同時又滿足效果要求不卡幀,一個是優化事件內代碼,減少代碼量,二就是做函數節流。
大部分節流都采用時間做節流,即時間間隔小於多少的不再調用,但同時保證一個最小調用間隔。(否則拖拽類的節流都將無效果),也可以用調用次數做節流,但要考慮最后一次調用需要要執行。
可以參考:淺談JavaScript的函數節流 (http://www.alloyteam.com/2012/11/javascript-throttle/)
【設計模式】
這方面被問到的比較多的有觀察者模式,職責鏈模式,工廠模式。主要是應用於js開發組件中會經常涉及,純粹的頁面業務邏輯可能涉及不多。比如如何去設計一個前端UI組件,應該共開出哪些方法,應該提供哪些接口,應該提供哪些事件。哪部分邏輯流程應該開放出去讓用戶自行編寫,如何實現組件與組件之間的通信,如何實現高內聚低耦合,如何實現組件的高復用等等。
【CSS垂直居中方法】
幾個出現頻率很高的CSS問題就是經典的垂直居中問題。這個問題又可以細分為,被垂直居中的元素是否定高,是文字還是塊,文字是單行還是多行文字等等。這可以百度下,有N種解決方案,主要還是看應用場景的限制。
【自適應布局】
這個問題可以划分為,左固定右自適應寬度,上固定下固定中間自適應高度等等布局要求。關於左右自適應的,不低於10種解決方案,還要看dom結構要求是並列還是嵌套,是否允許有父級元素,是否允許使用CSS3,是否有背景色,是否要兩列等高等等。而關於自適應高度的解決方案就略少一些,大致也就是靠css3的calc屬性,內padding,絕對定位后拉伸,動態js計算等等解決方案,同樣也是要看應用場景能用哪個。
【移動端自適應】
比如說2倍屏,3倍屏的自適應等
【附注】
該文是我扒自微博,特此感謝博主@IT程序員 && 酷勤網。這里純屬手打,可能會出現部分錯誤,童鞋們若有發現的或者補充的,歡迎在下面討論。也希望對眾多的面試人提供幫助~~~