編譯地址:Interviewing a front-end developer
作者:Alex MacCaw
譯者:myownghost
原文地址:http://ourjs.com/detail/52c4145d7986593603000009
注:之前我們介紹過(guò):一名靠譜的JavaScript程序員應(yīng)備的素質(zhì)雹拄,從程序員的角度提出要去學(xué)習(xí)哪些知識(shí),下面這篇文章從面試官的角度介紹到面試時(shí)可能會(huì)問(wèn)到的一些問(wèn)題掌呜。
我在Twitter和Stripe的一部分工作內(nèi)容是面試前端工程師。其實(shí)關(guān)于面試你可能很有自己的一套坪哄,這里我想跟你們分享一下我常用的方法质蕉。
不過(guò)我想先給你們一個(gè)忠告,招聘是一件非常艱巨的任務(wù)翩肌,在45分鐘內(nèi)指出一名侯選人是否合適是你需要完成的任務(wù)模暗。不過(guò)面試的最大問(wèn)題是每個(gè)人都會(huì)想著去雇傭他們自己,任何通過(guò)我面試的人想法大都跟我差不多(注:因?yàn)槟憧倳?huì)問(wèn)你自己關(guān)心和知道的問(wèn)題)念祭,這其實(shí)不是一件好事兑宇。因此我之前的決定都有很大碰運(yùn)氣的成分。不過(guò)粱坤,這也是一個(gè)良好的開(kāi)端隶糕。
最理想的情況下是,侯選人有一個(gè)全面的Github“簡(jiǎn)歷”站玄,這樣我們可以同時(shí)通過(guò)他們的開(kāi)源項(xiàng)目了解他們枚驻。我經(jīng)常會(huì)瀏覽他們的代碼然后針對(duì)一些特定的代碼設(shè)計(jì)問(wèn)一些問(wèn)題。如果侯選人有非常好的開(kāi)源項(xiàng)目記錄株旷,接下來(lái)的面試會(huì)直接去檢驗(yàn)他們的團(tuán)隊(duì)協(xié)作精神再登。否則,我不得不去問(wèn)他們一些代碼方面的問(wèn)題了。
我的面試非常有實(shí)踐性锉矢,全部是寫(xiě)代碼梯嗽。沒(méi)有抽象和理論上的東西(注:作者是個(gè)行業(yè)派),其他的面試官很可能會(huì)問(wèn)這些問(wèn)題沽损,但是我認(rèn)為他們前端編程的能力是值得商榷的灯节。我問(wèn)的問(wèn)題大多看上去非常簡(jiǎn)單,但是每組問(wèn)題都能讓我考查侯選人某一方面JavaScript的知識(shí)缠俺。
第一部分:Object Prototypes (對(duì)象原型)
剛開(kāi)始很簡(jiǎn)單显晶。我會(huì)讓侯選人去定義一個(gè)方法,傳入一個(gè)string
類型的參數(shù)壹士,然后將string
的每個(gè)字符間加個(gè)空格返回磷雇,例如:
spacify('hello world') // => 'h e l l o w o r l d'
盡管這個(gè)問(wèn)題似乎非常簡(jiǎn)單,其實(shí)這是一個(gè)很好的開(kāi)始躏救,尤其是對(duì)于那些未經(jīng)過(guò)電話面試的侯選人——他們很多人聲稱精通JavaScript唯笙,但通常連一個(gè)簡(jiǎn)單的方法都不會(huì)寫(xiě)。
下面是正確答案盒使,有時(shí)侯選人可能會(huì)用一個(gè)循環(huán)崩掘,這也是一種可接受的答案。
function spacify(str) {
return str.split('').join(' ');
}
接下來(lái)少办,我會(huì)問(wèn)侯選人苞慢,如何把這個(gè)方法放入String
對(duì)象上面,例如:
'hello world'.spacify();
問(wèn)這個(gè)問(wèn)題可以讓我考察侯選人是否對(duì)function prototypes
(方法原型)有一個(gè)基本的理解英妓。這個(gè)問(wèn)題會(huì)經(jīng)常引起一些有意思的討論:直接在對(duì)象的原型(prototypes
)上添加方法是否安全挽放,尤其是在Object對(duì)象上。最后的答案可能會(huì)像這樣:
String.prototype.spacify = function(){
return this.split('').join(' ');
};
到這兒蔓纠,我通常會(huì)讓侯選人解釋一下函數(shù)聲明和函數(shù)表達(dá)式的區(qū)別辑畦。
第二部分:參數(shù)
arguments
下一步我會(huì)問(wèn)一些簡(jiǎn)單的問(wèn)題去考察侯選人是否理解參數(shù)(arguments
)對(duì)象。我會(huì)讓他們定義一個(gè)未定義的log
方法作為開(kāi)始腿倚。
log('hello world')
我會(huì)讓侯選人去定義log
纯出,然后它可以代理console.log
的方法。正確的答案是下面幾行代碼敷燎,其實(shí)更好的侯選人會(huì)直接使用apply
.
function log(msg) {
console.log(msg);
}
他們一旦寫(xiě)好了暂筝,我就會(huì)說(shuō)我要改變我調(diào)用log
的方式,傳入多個(gè)參數(shù)硬贯。我會(huì)強(qiáng)調(diào)我傳入?yún)?shù)的個(gè)數(shù)是不定的乖杠,可不止兩個(gè)。這里我舉了一個(gè)傳兩個(gè)參數(shù)的例子澄成。
log('hello', 'world');
希望你的侯選人可以直接使用apply
胧洒。有時(shí)人他們可能會(huì)把apply
和call
搞混了畏吓,不過(guò)你可以提醒他們讓他們微調(diào)一下。傳入console
的上下文也非常重要卫漫。
function log(){
console.log.apply(console, arguments);
};
接下來(lái)我會(huì)讓侯選人給每一個(gè)log
消息添加一個(gè)"(app)"的前輟菲饼,比如:
'(app) hello world'
現(xiàn)在可能有點(diǎn)麻煩了。好的侯選人知道arugments
是一個(gè)偽數(shù)組列赎,然后會(huì)將他轉(zhuǎn)化成為標(biāo)準(zhǔn)數(shù)組宏悦。通常方法是使用Array.prototype.slice
,像這樣:
function log(){
var args = Array.prototype.slice.call(arguments);
args.unshift('(app)');
console.log.apply(console, args);
};
第三部分:上下文
下一組問(wèn)題是考察侯選人對(duì)上下文和this的理解包吝。我先定義了下面一個(gè)例子饼煞。注意count
屬性不是只讀取當(dāng)前下下文的。
var User = {
count: 1,
getCount: function() {
return this.count;
}
};
我又寫(xiě)了下面幾行诗越,然后問(wèn)侯選人log
輸出的會(huì)是什么砖瞧。
console.log(User.getCount());
var func = User.getCount;
console.log(func());
這種情況下,正確的答案是1
和undefined
嚷狞。你會(huì)很吃驚块促,因?yàn)橛泻芏嗳吮贿@種最基礎(chǔ)的上下文問(wèn)題絆倒。func
是在winodw的上下文中被執(zhí)行的床未,所以會(huì)訪問(wèn)不到count
屬性竭翠。我向侯選人解釋了這點(diǎn),然后問(wèn)他們?cè)趺礃颖WCUser總是能訪問(wèn)到func
的上下文薇搁,即返回正即的值:1
正確的答案是使用Function.prototype.bind
斋扰,例如:
var func = User.getCount.bind(User);
console.log(func());
接下來(lái)我通常會(huì)說(shuō)這個(gè)方法對(duì)老版本的瀏覽器不起作用,然后讓侯選人去解決這個(gè)問(wèn)題啃洋。很多弱一些的侯選人在這個(gè)問(wèn)題上犯難了褥实,但是對(duì)于你來(lái)說(shuō)雇傭一個(gè)理解apply
和call
的侯選人非常重要。
Function.prototype.bind = Function.prototype.bind || function(context){
var self = this;
return function(){
return self.apply(context, arguments);
};
}
第四部分:彈出窗口(Overlay library)
面試的最后一部分裂允,我會(huì)讓侯選人做一些實(shí)踐,通過(guò)做一個(gè)‘彈出窗口’的庫(kù)哥艇。我發(fā)現(xiàn)這個(gè)非常有用绝编,它可以全面地展示一名前端工程師的技能:HTML,CSS和JavaScript。如果侯選人通過(guò)了前面的面試貌踏,我會(huì)馬上讓他們回答這個(gè)問(wèn)題十饥。
實(shí)施方案是由侯選人自己決定的,但是我也希望他們能通過(guò)以下幾點(diǎn)來(lái)實(shí)現(xiàn):
在遮罩中最好使用position中的fixed
代替absolute
屬性祖乳,這樣即使在滾動(dòng)的時(shí)侯逗堵,也能始終讓遮罩始蓋住整個(gè)窗口。當(dāng)侯選人忽略時(shí)我會(huì)提示他們這一點(diǎn)眷昆,并讓他們解釋fixed
和absolute
定位的區(qū)別蜒秤。
.overlay {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
background: rgba(0,0,0,.8);
}
他們?nèi)绾巫尷锩娴膬?nèi)容居中也是需要考察的一點(diǎn)汁咏。一些侯選人會(huì)選擇CSS和絕對(duì)定位,如果內(nèi)容有固定的寬作媚、高這是可行的攘滩。否則就要使用JavaScript.
.overlay article {
position: absolute;
left: 50%;
top: 50%;
margin: -200px 0 0 -200px;
width: 400px;
height: 400px;
}
我也會(huì)讓侯選人確保當(dāng)遮罩被點(diǎn)擊時(shí)要自動(dòng)關(guān)閉,這會(huì)很好地考查事件冒泡機(jī)制的機(jī)會(huì)纸泡。通常侯選人會(huì)在overlay上面直接綁定一個(gè)點(diǎn)擊關(guān)閉的方法漂问。
$('.overlay').click(closeOverlay);
這是個(gè)方法,不過(guò)直到你認(rèn)識(shí)到點(diǎn)擊窗口里面的東西也會(huì)關(guān)閉overlay的時(shí)侯——這明顯是個(gè)BUG女揭。解決方法是檢查事件的觸發(fā)對(duì)象和綁定對(duì)象是否一致蚤假,從而確定事件不是從子元素里面冒上來(lái)的,就像這樣:
$('.overlay').click(function(e){
if (e.target == e.currentTarget)
closeOverlay();
});
其他方面
當(dāng)然這些問(wèn)題只能覆蓋前端一點(diǎn)點(diǎn)的知識(shí)的吧兔,還有很多其他的方面你有可能會(huì)問(wèn)到磷仰,像性能,HTML5 API, AMD和CommonJS模塊模型掩驱,構(gòu)造函數(shù)(constructors)芒划,類型和盒子模型(box model)。根據(jù)侯選人的情況欧穴,我經(jīng)常會(huì)隨機(jī)提些問(wèn)題民逼。