這道面試題萝风,當(dāng)初我面試的時候被問過兩次嘀掸,因此比較深,此外规惰,我記得還有設(shè)計模式的考察睬塌,所以,有深刻的體會歇万。
面試題主要考察什么
面試不是個輕松的活揩晴,不管是對面試官還是面試者都一樣。對于面試官來說贪磺,別的先不管硫兰,首先一點技術(shù)要過關(guān),對候選人的基本要求就是基礎(chǔ)扎實寒锚,有相關(guān)項目經(jīng)驗劫映,有解決問題的能力,思路清晰壕曼,易于溝通苏研。而對于面試者來說要技術(shù)扎實等浊,知識面要廣腮郊,要有技術(shù)閃光點,對于各種技術(shù)提起來都知道點筹燕,但經(jīng)不起深層次的詢問轧飞,這種‘一瓶子水不滿,半瓶子水晃地’現(xiàn)象很不受面試官的喜歡撒踪。
雖然过咬,我工作的時間不長,但被面試過制妄,也面試過別人掸绞。所以,將這道題被問的情況和自己的體會理解分享給大家耕捞。
注:面試公司 去哪兒衔掸,360
用 html + css 實現(xiàn)一個彈出框
注:這是按照面試官的預(yù)想可能出現(xiàn)的情況設(shè)定的,不同的面試者臨場發(fā)揮不一樣俺抽,面試官可能問的問題也有所變化敞映,但歸根結(jié)底,這個系列的問題大致如下磷斧。
這里你在回答前需要問清楚實現(xiàn)有什么限制沒振愿,如果沒有捷犹,你可以以任意的方式來實現(xiàn);如果有冕末,問清楚限制萍歉,一般限制有如下情況,一種定寬定高档桃,另一種不定寬高(補丁寬高一般用js控制)翠桦,但是使用css3亦可實現(xiàn),如果你回答出一種胳蛮,面試官往往會問有沒有其他的實現(xiàn)方法销凑,如果面試管這樣問了,你如果仅炊,回答沒有斗幼,會被扣分的。面試會進(jìn)入下一個環(huán)節(jié)抚垄。
彈出框垂直水平居中
html:
<div class="box-default box-wh box-vc-mar">this is a pop-up box</div>
css:
.box-default {
position: fixed;
top: 50%;
left: 50%;
z-index: 99;
padding: 20px;
background-color: white;
border: 1px solid #ccc;
border-radius: 8px;
}
.box-wh {
width: 200px;
height: 200px;
}
.box-vc-mar {
margin-left: -100px;
margin-top: -100px;
}
如果彈出窗的寬高不定
html:
<div class="box-default">this is a pop-up box</div>
css:
.box-default {
position: fixed;
top: 50%;
left: 50%;
z-index: 99;
padding: 20px;
background-color: white;
border: 1px solid #ccc;
border-radius: 8px;
}
.box-vc-mar {
margin-left: -100px;
margin-top: -100px;
}
js:
var $box = $('.box-default'),
bw = $box.width(),
bh = $box.height();
$box.css({
marginLeft: - bw/2 + 'px',
marginTop: - bh/2 + 'px',
});
有沒有其他方式實現(xiàn)不定寬高的彈出窗
答案:有
html:
<div class="box-default box-vc-trf">this is a pop-up box that only html+css</div>
css:
.box-default {
position: fixed;
top: 50%;
left: 50%;
z-index: 99;
padding: 20px;
background-color: white;
border: 1px solid #ccc;
border-radius: 8px;
}
.box-vc-trf {
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
4.如果給彈出窗加一個遮罩層該如何實現(xiàn)
html:
<div class="box-default box-vc-trf">this is a pop-up box that only html+css</div>
<div class="mask"></div>
css:
.box-default {
position: fixed;
top: 50%;
left: 50%;
z-index: 99;
padding: 20px;
background-color: white;
border: 1px solid #ccc;
border-radius: 8px;
}
.box-vc-trf {
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 98;
background-color: #000;
opacity: 0.75;
filter: alpha(opacity=75);
}
下面的問題就問的比較深了蜕窿,牽涉到了一些簡單業(yè)務(wù)實現(xiàn)
觸發(fā)按鈕實現(xiàn)彈窗
根據(jù)是之前實現(xiàn)的結(jié)果,如果在頁面中有一個按鈕呆馁,通過觸發(fā)鈕如何實現(xiàn)彈出窗以及實現(xiàn)關(guān)閉彈出窗
示例代碼如下:
html:
<div class="box-default box-vc-trf">this is a pop-up box that only html+css</div>
<div class="mask"></div>
<button id="btn">click it</button>
css:
.box-default {
position: fixed;
top: 50%;
left: 50%;
z-index: 99;
display: none;
padding: 20px;
background-color: white;
border: 1px solid #ccc;
border-radius: 8px;
}
.box-in {
display: block;
}
.box-vc-trf {
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 98;
display: none;
background-color: #000;
opacity: 0.75;
filter: alpha(opacity=75);
}
.mask-in {
display: block;
}
js:
var $box = $('.box-default'),
$mask = $('.mask'),
$btn = $('#btn');
$btn.on('click', function(event) {
event.preventDefault();
$box.addClass('box-in');
$mask.addClass('mask-in');
});
$mask.on('click', function(event) {
event.preventDefault();
$(this).removeClass('mask-in');
$box.removeClass('box-in');
});
這個只是我的實現(xiàn)桐经,每個人的實現(xiàn)都會有所不同。
此外浙滤,像這里如何關(guān)閉彈出窗的實現(xiàn)方式阴挣,并不一定要通過觸發(fā)遮罩層來實現(xiàn),我們常見的實現(xiàn)是在彈出窗中加一個關(guān)閉按鈕纺腊。像在這里這種模棱兩可的地方畔咧,往往存在陷阱,我建議在你給出答案前先問清楚這個關(guān)閉彈出窗要如何實現(xiàn),并給出自己的方案,因為在實際的項目開發(fā)的過程有些細(xì)節(jié)問題產(chǎn)品經(jīng)理并不會面面俱到否副,會有疏漏的地方,而作為一個前端你要及時的提出來拜隧,進(jìn)行溝通確認(rèn),這里可能會考察你的觀察趁仙,判斷和溝通能力洪添。但有些時候你問過后,面試官會對你笑笑幸撕,讓你自由發(fā)揮薇组,你這時就會明白,這是一處坑坐儿。但有時候不是這樣律胀,所以宋光,面試時要主動與面試官溝通,避免因細(xì)節(jié)問題在面試過程中被降分炭菌。
如果在頁面中有多個按鈕罪佳,那么這個彈出窗要如何實現(xiàn)
同上,根據(jù)之前的建議在回答問題之前要問清楚問題中模棱兩可的地方黑低。
1.多個按鈕是不是成百上千個赘艳,或者就是幾個。
2.是否觸發(fā)不同按鈕彈出的窗口現(xiàn)實的內(nèi)容不同克握。
同時也可以不問蕾管,你只要明白要考察的知識點即可,問只是讓你更清楚的知曉面試官的考察點菩暗。
html:
<div class="box-default box-vc-trf">this is a pop-up box that only html+css</div>
<div class="mask"></div>
<button class="btn">click</button>
<button class="btn">click2</button>
<button class="btn">click3</button>
<button class="btn">click4</button>
<button class="btn">click5</button>
<button class="btn">click6</button>
css:
css 同上個示例
js:
$(function(){
var $box = $('.box-default'),
$mask = $('.mask');
$mask.on('click', function(event) {
event.preventDefault();
hideMask();
});
$('.btns').forEach(function(el, i) {
el.on('click', function(event) {
event.preventDefault();
var content = getText($(this));
showMask(content);
}
});
function getText(obj) {
return obj.text()
}
function showMask(content) {
$box.addClass('box-in').html(content);
$mask.addClass('mask-in');
}
function hideMask(obj) {
$mask.removeClass('mask-in');
$box.removeClass('box-in');
}
});
這里主要考察了兩點:
1.js基礎(chǔ)是否扎實
- 表現(xiàn)和行為的分離
- 可維護(hù)性
- 可擴展性
2.是否使用了事件代理
代碼修改如下:
$(function(){
...
$(document.body).on('click', '.btn', function(event) {
event.preventDefault();
var content = getText($(this));
showMask(content);
});
...
});
有時候面試官會讓你用原生js來實現(xiàn)事件代理掰曾,那么我們應(yīng)該如何回答呢?
由于事件委托可以實現(xiàn)目標(biāo)對象的隱藏停团,在開發(fā)這對于我們保護(hù)一些核心的對象非常有用旷坦,不過實話來說,在JavaScript中就是call佑稠,apply的使用秒梅,因為js中只有這兩個方法提供了改變當(dāng)前函數(shù)內(nèi)部this作用域的功能。當(dāng)然這只是對象的委托舌胶,而要實現(xiàn)對類的委托則要相對復(fù)雜些捆蜀,對類的實現(xiàn)大家有興趣的可以參考以下Prototype.js或Jquery中的相應(yīng)實現(xiàn)。
事件代理就要改變偵聽器的位置辆琅,或者說改變事件綁定的對象漱办。得益于js的事件傳播機制,實現(xiàn)起來非常容易婉烟。
下面這個例子大家都可能見過:
html:
<ul id="nav">
<li><a >CSDN</a></li>
<li><a >Segmentdefault</a></li>
<li><a >github</a></li>
<li><a >稀土掘金</a></li>
<li><a >博客園</a></li>
</ul>
js:
window.onload = function(){
var nav = document.getElementById("nav");
nav.onclick = function () {
var e = arguments[0] || window.event,
target = e.srcElement ? e.srcElement : e.target;
if (target.nodeName.toLowerCase() === 'a')
alert(target.innerHTML);
return false;
}
}
var addEvent = (function () {
if (document.addEventListener) {
return function (el, type, fn) {
el.addEventListener(type, fn, false);
};
} else if (document.attachEvent) {
return function (el, type, fn) {
el.attachEvent('on' + type, fn);
}
} else {
el['on' + type] = fn
}
})();
上面這個事件監(jiān)聽的兼容性代碼片段,是面試官問我是否對jQuery源碼有所了解暇屋,我當(dāng)然說有似袁,就讓我說一下如何實現(xiàn)。
好了咐刨,關(guān)于事件代理的問題就不深入討論了昙衅,我們接著了解關(guān)于彈出窗的其他問題。
遮罩層的共用問題
同一個頁面我們可以考慮定鸟,直接在頁面中加一個表示遮罩層的div而涉,
但是對于不同的頁面我們最好用js來控制。
問題:這里面試管會問联予,如何實現(xiàn)遮罩層的共享啼县?
我們通常會寫下面的一個代碼片段:
function createMask() {
return $(document.body).append($('<div>').addClass('mask'));
}
雖然材原,這樣添加一個遮罩層,在隱藏的時候可以使用remove()移除它季眷,但顯然這樣在頁面中頻繁的添加余蟹,刪除dom元素不合理。
問題:有沒有什么方法可以對它進(jìn)行優(yōu)化子刮?
我們可能會考慮對它進(jìn)行優(yōu)化威酒,先在全局創(chuàng)建一個這個遮罩層div,用一個變量來引用它挺峡。代碼如下:
var mask = $(document.body).append($('<div>').addClass('mask'));
這樣頁面就只會創(chuàng)建一個遮罩層div葵孤,但是可能出現(xiàn),我們在使用的過程中不會用到這個div橱赠,這樣我們就會造成資源的浪費佛呻,dom的節(jié)點就會平白多出一個無用的div。
這時我們可以借助一個變量來判斷是否創(chuàng)建過div病线。代碼如下:
var mask;
function createMask() {
if (mask) {
return mask;
} else {
mask = $('<div/>').addClass('mask').appendTo($(document.body));
return mask;
}
}
細(xì)心的你是否發(fā)現(xiàn)這是一個單例吓著?
當(dāng)你在面試前對這個問題有研究,你說用一個單例模式來解決送挑,面試官會讓你先實現(xiàn)绑莺,然后讓你說說單例模式的理解,最后詢問相關(guān)的問題惕耕。如:什么是單例模式纺裁,單例模式有何優(yōu)缺點,如何使用單例模式司澎。
但是也有時候面試官會讓你直接使用一個設(shè)計模式來對它進(jìn)行優(yōu)化欺缘?
在這里,面試官的詢問方向跟面試官的知識面和掌控度有關(guān)挤安。所以谚殊,面試大廠或者面試中/高級工程師的童鞋還是把自己的所學(xué)知識技能系統(tǒng)化比較好。
你發(fā)現(xiàn)上面那段代碼實現(xiàn)有哪里不妥嗎蛤铜?對了嫩絮,你在函數(shù)體內(nèi)改變了函數(shù)外的變量mask的引用,在多人協(xié)作的項目中围肥,你寫的createMask是一個不安全的函數(shù)剿干,此外我們開發(fā)中應(yīng)盡量避免像mask這樣的全局變量使用,用一個局部變量如何來解決這個問題呢穆刻,我想很多同學(xué)會想到閉包置尔,修改后的代碼如下:
function createMask() {
var mask;
return function() {
if (mask) {
return mask;
} else {
mask = $('<div/>').addClass('mask').appendTo($(document.body));
return mask;
}
}
}
好吧,到了這里你可能在心里想‘這下總算完了吧’氢伟,是的榜轿,我想說的是這道題你答成這個樣子幽歼,對于中級工程師來說已經(jīng)過關(guān)了,但是對于高級工程師來說差导,你還需要對這個代碼進(jìn)行優(yōu)化试躏,如果經(jīng)常研究源碼的童鞋會見到這樣寫的代碼片段:
function createMask() {
var mask;
return function() {
return mask || mask = $('<div/>').addClass('mask').appendTo($(document.body));
}
}
對于那些開發(fā)框架,常用庫或插件的大牛來說设褐,同樣的功能颠蕴,同樣的性能,不會多浪費一個字符助析。
如果是面試高級工程師犀被,可能還會被問到,如何多個功能都要用到單例模式外冀,該如何解決寡键?
function singleton(fn) {
var res;
return function() {
return res || (res = fn.apply(this, arguments))
}
}
var createMask = singleton(function () {
return $('<div/>').addClass('mask').appendTo($(document.body));
});
其實,這里又用到了另一種設(shè)計模式——橋接模式雪隧。
面試到這里一般就算完了西轩。通過上面的代碼我們發(fā)現(xiàn),設(shè)計模式也不是什么洪水猛獸脑沿,只不過是設(shè)計模式的使用靈活多變藕畔,但要想真正完全掌握設(shè)計模式,不是看兩篇文章就行的最重要的還是要多想庄拇,多實踐注服。