面試web前端人員

轉自:https://segmentfault.com/a/1190000000375138前端

我在Twitter和Stripe的一部分工做內容是面試前端工程師。其實關於面試你可能頗有本身的一套,這裏我想跟大家分享一下我經常使用的方法。面試

不過我想先給大家一個忠告,招聘是一件很是艱鉅的任務,在45分鐘內指出一名侯選人是否合適是你須要完成的任務。不過面試的最大問題是每一個人都會想着去僱傭他們本身,任何經過我面試的人想法大都跟我差很少(注:由於你總會問你本身關心和知道的問題),這其實不是一件好事。所以我以前的決定都有很大碰運氣的成分。不過,這也是一個良好的開端。編程

最理想的狀況下是侯選人有一個全面的Github「簡歷」,這樣咱們能夠同時經過他們的開源項目瞭解他們。我常常會瀏覽他們的代碼而後針對一些特定的代碼設計問一些問題。若是侯選人有很是好的開源項目記錄,接下來的面試會直接去檢驗他們的團隊協做精神。不然,我不得不去問他們一些代碼方面的問題了。segmentfault

個人面試很是有實踐性,所有是寫代碼。沒有抽象和理論上的東西(注:做者是個行業派),其餘的面試官極可能會問這些問題,可是我認爲他們前端編程的能力是值得商榷的。我問的問題大多看上去很是簡單,可是每組問題都能讓我考查侯選人某一方面JavaScript的知識。數組

第一部分:Object Prototypes (對象原型)

剛開始很簡單。我會讓侯選人去定義一個方法,傳入一個string類型的參數,而後將string的每一個字符間加個空格返回,例如:瀏覽器

spacify('hello world') // => 'h e l l o  w o r l d'    

儘管這個問題彷佛很是簡單,其實這是一個很好的開始,尤爲是對於那些未通過電話面試的侯選人——他們不少人聲稱精通JavaScript,但一般連一個簡單的方法都不會寫。安全

下面是正確答案,有時侯選人可能會用一個循環,這也是一種可接受的答案。前端工程師

function spacify(str) {  
   return str.split('').join(' '); }

接下來,我會問侯選人,如何把這個方法放入String對象上面,例如:app

'hello world'.spacify();

問這個問題可讓我考察侯選人是否對function prototypes(方法原型)有一個基本的理解。這個問題會常常引發一些有意思的討論:直接在對象的原型(prototypes)上添加方法是否安全,尤爲是在Object對象上。最後的答案可能會像這樣:函數

String.prototype.spacify = function(){  
   return this.split('').join(' '); };

到這兒,我一般會讓侯選人解釋一下函數聲明和函數表達式的區別。

第二部分:參數 arguments

下一步我會問一些簡單的問題去考察侯選人是否理解參數(arguments)對象。我會讓他們定義一個未定義的log方法做爲開始。

log('hello world')

我會讓侯選人去定義log,而後它能夠代理console.log的方法。正確的答案是下面幾行代碼,其實更好的侯選人會直接使用apply.

function log(msg) {  
   console.log(msg); }

他們一旦寫好了,我就會說我要改變我調用log的方式,傳入多個參數。我會強調我傳入參數的個數是不定的,可不止兩個。這裏我舉了一個傳兩個參數的例子。

log('hello', 'world');

但願你的侯選人能夠直接使用apply。有時人他們可能會把apply和call搞混了,不過你能夠提醒他們讓他們微調一下。傳入console的上下文也很是重要。

function log(){ 
 console.log.apply(console, arguments); };

接下來我會讓侯選人給每個log消息添加一個"(app)"的前輟,好比:

'(app) hello world'

如今可能有點麻煩了。好的侯選人知道arugments是一個僞數組,而後會將他轉化成爲標準數組。一般方法是使用Array.prototype.slice,像這樣:

function log(){  
   var args = Array.prototype.slice.call(arguments);    args.unshift('(app)');  
   console.log.apply(console, args); };

第三部分:上下文

下一組問題是考察侯選人對上下文和this的理解。我先定義了下面一個例子。注意count屬性不是隻讀取當前下下文的。

var User = {  count: 1,  getCount: function() {    return this.count;  } };

我又寫了下面幾行,而後問侯選人log輸出的會是什麼。

console.log(User.getCount());
var func = User.getCount;
console.log(func());

這種狀況下,正確的答案是1和undefined。你會很吃驚,由於有不少人被這種最基礎的上下文問題絆倒。func是在winodw的上下文中被執行的,因此會訪問不到count屬性。我向侯選人解釋了這點,而後問他們怎麼樣保證User老是能訪問到func的上下文,即返回正即的值:1

正確的答案是使用Function.prototype.bind,例如:

var func = User.getCount.bind(User);
console.log(func());

接下來我一般會說這個方法對老版本的瀏覽器不起做用,而後讓侯選人去解決這個問題。不少弱一些的侯選人在這個問題上犯難了,可是對於你來講僱傭一個理解apply和call的侯選人很是重要。

Function.prototype.bind = Function.prototype.bind || function(context){  
   var self = this;  
   return function(){    
       return self.apply(context, arguments);    }; }

第四部分:彈出窗口(Overlay library)

面試的最後一部分,我會讓侯選人作一些實踐,經過作一個‘彈出窗口’的庫。我發現這個很是有用,它能夠全面地展現一名前端工程師的技能:HTML,CSS和JavaScript。若是侯選人經過了前面的面試,我會立刻讓他們回答這個問題。

實施方案是由侯選人本身決定的,可是我也但願他們能經過如下幾點來實現:

在遮罩中最好使用position中的fixed代替absolute屬性,這樣即便在滾動的時侯,也能始終讓遮罩始蓋住整個窗口。當侯選人忽略時我會提示他們這一點,並讓他們解釋fixed和absolute定位的區別。

.overlay {  
   position: fixed;  
   left: 0;  
   right: 0;  
   bottom: 0;  
   top: 0;  
   background: rgba(0,0,0,.8);
}

他們如何讓裏面的內容居中也是須要考察的一點。一些侯選人會選擇CSS和絕對定位,若是內容有固定的寬、高這是可行的。不然就要使用JavaScript.

.overlay article {  
       position: absolute;  
       left: 50%;  
       top: 50%;  
       margin: -200px 0 0 -200px;  
       width: 400px;  
       height: 400px;
}

我也會讓侯選人確保當遮罩被點擊時要自動關閉,這會很好地考查事件冒泡機制的機會。一般侯選人會在overlay上面直接綁定一個點擊關閉的方法。

$('.overlay').click(closeOverlay);

這是個方法,不過直到你認識到點擊窗口裏面的東西也會關閉overlay的時侯——這明顯是個BUG。解決方法是檢查事件的觸發對象和綁定對象是否一致,從而肯定事件不是從子元素裏面冒上來的,就像這樣:

$('.overlay').click(function(e){  
   if (e.target == e.currentTarget) closeOverlay(); });
相關文章
相關標籤/搜索