【長坑慎入】2014阿里前端線上筆試題解答-1
2014年阿里的前端線上筆試題目區分度十分的高,感覺十分有意義。所以在這裡做一些分析,也希望能豐富一下自己。這裡已經有一個帖子,但是因為其中作者有一部分也沒有解釋,而且文章的版式比較混亂,所以決定自己動手再分析一下。
No. 1
題目:
下圖綠色區域的寬度為100%,其中有三個矩形,第一個矩形的寬度是200px,第二個和第三個矩形的寬度相等。請使用CSS3中的功能實現它們的佈局。
已知HTML結構是:
<div class="box">
<div class="item">column 1</div>
<div class="item">column 2</div>
<div class="item">column 3</div>
</div>
解答:
【2013/10/16 更新】
十分感謝 @酷劍 的指正。回去仔細查了一下MDN,發現本題一開始的解答有誤。回頭查了查原帖,發現原帖正確的使用 box-flex
的屬性,而我的解答並不規範。更新解答如下:
.box {
background-color: #619B99;
display: -webkit-box;
height: 40px;
padding: 10px;
padding-right: 0px;
width: 100%;
}
.box>div {
height: 40px;
background-color: #EEEEEE;
margin-right: 10px;
-webkit-box-flex: 1;
}
.box div:first-of-type {
width: 200px;
-webkit-box-flex: 0;
}
這裡其實 box-flex
的含義在於規定框是否具有可伸縮尺寸。我個人總結的規則如下:
- 當box-flex: 0時,框的空間固定而不伸縮;
- 當 box-flex: n時,框的空間大約會按照剩餘寬度的 n/m 伸縮,m為所有設定了box-flex值的和。
- 當給有flex的box設定了大小時,該box將擁有設定的空間與flex分配的空間之和。
例如父元素有500的空間,其中五個元素設定flex為1,則五個元素的寬度均為100;一個設定為flex:0、寬度180,則剩下的元素均分320的寬度,也即每個80;一個設定flex:6,則該元素分的6/10的寬度即300,剩餘的元素各分1/10的寬度即50;一個元素設定為flex:1,同時設定寬度100,則該元素分得100+(500-100)/5=180的寬度,剩餘的元素分的(500-100)/5=80的寬度。
(實測發現這裡並不是很準確,準確的說當設定了flex的元素內部沒有其他元素時,框的寬度會按照box-flex設定的那樣按比例填充,但如果有元素和邊距等情況,這個比例就僅僅是個大約的值了。)
實際上box-flex是個特別有用的工具,其一勞永逸的解決了當一個box中有元素有固定值,而又要求剩下的元素按比例浮動的情況。像這種問題之前都是使用絕對定位,將固定的元素採取 absolute 定位的方式,然後剩下的元素使用margin留出浮動元素留下的位子。但是當固定的元素過多且混雜出現時,使用絕對定位的方法將不能優雅的解決這個問題,那麼flex模型就能展現它的力量了。
No.2
題目:
有兩個盒子 A、B,B 在 A 盒子中,它們的 CSS 是這麼定義的:
.A {
position: relative;
width: 500px;
height: 500px;
background-color: green;
}
.B {
position: absolute;
max-width: 300px;
max-height: 300px;
background-color: blue;
}
如何實現 B 在 A 中水平方向和垂直方向居中?
解答:
作者在原文裡表示可以使用CSS3的 box-align
和 box-pack
的方法(W3C連結如下box-align,box-pack),但是在實際測試中發現,如果B的定位不是 absolute
(而是 relative
或者 static
)那麼如下追加的程式碼是有效的:
.A {
display: -webkit-box;
-webkit-box-align: center;
-webkit-box-pack: center;
}
但是當B的定位是絕對定位時,使用CSS3的box進行定位就起不到應有的效果。這裡我們可以簡單的看以下CSS的四種定位的原理(可參見mdn的解釋:css position 以及quicksmode的這篇博文:the position declaration)。
static
:預設定位,不可使用top
right
bottom
left
四種屬性(以下簡稱TRBL);relative
:相對定位,指的是針對預設定位的位置而產生偏移,可以使用TRBL調整定位的偏移量,但是元素本身還在文件流中佔據位置;absolute
:絕對定位,指標對上一級非預設定位的位置(即上一級非static
定位的父元素的位置)而產生的偏移,可用TRBL調整偏移量,與相對定位不同的是,元素本身漂出文件流,不再佔據位置;fix
:固定定位,錨定瀏覽器視窗的一種定位方式,可用TRBL調整偏移量。
這裡B元素使用了絕對定位,也就是其偏移是針對A元素而計算的,可以使用TRBL進行調整。所以說莫非這裡出題人是想讓我們採用原始的div居中方法?
在CSS2的時代,要將div水平垂直居中也算是個挺讓人頭疼的問題,其大致的方法有如下幾種:
外層元素寬度不固定,內層元素寬度固定:使用自動外邊距或負值外邊距兩種方式;
自動外邊距,這裡要求內層元素不能採取絕對定位:
.B { width: 100px; margin: 0 auto; }
負值外邊距,用到了TRBL屬性,要求內層元素採取絕對定位:
.B { width: 200px; position: absolute; left: 50%; margin-left: -100px; }
外層元素寬度固定,內層元素寬度不固定,採用表格法,要求內部元素不能採取絕對定位:
A. { display: table; } .B { display: table-cell; vertical-margin: center; }
增添HTML元素、使用Hack、使用JS等,不詳述之。
然而觀察上面的方法,題目中的限定條件是:外部元素寬度固定、內部元素寬度變動且絕對定位,這樣就導致上述的方法沒有一個可以滿足所需要求的。我認為如果不改變題目中的限定,可以使用負值外邊距的方法,用JS設定內層元素的margin值;或者直接在後面的CSS中修改內層元素的定位(設定為非絕對定位),然後使用CSS3的 box-align
和 box-pack
來實現,而這也是目前我認為實現效果最好,實現程式碼最為簡潔的實現方式。
其中如果附加JS,程式碼如下:
<script>
var b = document.getElementsByClassName('B')[0]
, l = b.offsetWidth
, h = b.offsetHeight
b.style.marginLeft = -l/2 + 'px';
b.style.marginTop = -h/2 + 'px';
</script>
No.8
題目:
現有程式碼如下:
var foo = 1;
function main(){
console.log(foo);
var foo = 2;
console.log(this.foo)
this.foo = 3;
}
請給出以下兩種方式呼叫函式時,輸出的結果,並說明原因。
var m1 = main(); var m2 = new main();
如果想要
var m1 = main()
產生的m1和前面的m2完全一致,又該如何改造main函式?
解答:
看到全域性變數與函式內區域性變數重名時,一定要先想到 hoisting (變數宣告提升規則)!
在第一種呼叫方式裡,函式內部宣告瞭區域性變數 foo
,因此其宣告被提升至最前。因此該段程式碼等價於:
function main(){
var foo;
console.log(foo);
foo = 2;
console.log(this.foo)
this.foo = 3;
}
在呼叫的時候,第一次輸出為undefined,因為區域性變數 foo
還沒有被賦值,第二次輸出為1,因為此時在非嚴格模式下 this
指代 window
物件。this.foo
即為全域性變數的 foo
。
在第二種呼叫方式裡,使用了原型鏈繼承的方法,可以參見我的這篇文章:JavaScript原型繼承工作原理,其中 new
運算子的作用等價於如下函式:
function New (f) {
var n = { '__proto__': f.prototype };
return function () {
f.apply(n, arguments);
return n;
};
}
則在進行 new
運算時,函式中的 this
實際上指代的是運算子後面所跟的建構函式的原型鏈。因為在 new
運算的時候,實際上執行建構函式的是這一步: f.apply(n, arguments);
也就是說在建構函式中的 this
實際上指向的是變數 n
,而 n
是一個除了原形鏈指向 f
的原形鏈之外一無所有的空物件,所以這裡的 this
實際上是指向了建構函式 f
的原形鏈。
所以這裡的輸出也就不難理解:因為建構函式 main()
本身的原形鏈為空,所以輸出 this.foo
的結果為 undefined。
然後是第二問:使m1與m2的結果完全一致。我們知道m2所得到的是類 main
的一個例項化物件,這裡要使得達到題目中的要求,就只能手工編寫原形鏈繼承,使 main
函式的返回結果為一個繼承自其本身的物件。這裡可以參考上面程式碼中 new
運算子的具體實現,編寫 main
函式如下:
function main(){
console.log(foo);
var foo = 2;
console.log(this.foo)
this.foo = 3;
//返回一個main的例項化物件
var n = {'__proto__': main.prototype};
//main.apply(n, arguments);
n.foo = 3;
return n;
}
這裡因為在 main
函式裡有 this.foo = 3
這一項,為原型新增了成員變數,但如果在這裡使用 apply
的方式為n新增這一屬性的話,將進行無限遞迴導致棧溢位。而採取其他的方式都不可避免的會帶來一些問題,所以直接給返回值n的屬性foo進行了賦值,也起到了同樣的效果。
相關文章
- 【長坑慎入】2014阿里前端線上筆試題解答-2阿里前端筆試
- 2014亞馬遜線上筆試題目亞馬遜筆試
- 美團網2014校招筆試題及解答(長沙站+哈爾濱站)薦筆試
- 2014亞馬遜線上筆試題目及解決方案(MMChess問題)亞馬遜筆試
- 熱乎的前端筆試/面試/跳坑筆記(指南)前端筆試面試筆記
- 前端筆試&面試爬坑系列---演算法前端筆試面試演算法
- 前端筆試&面試爬坑系列—演算法前端筆試面試演算法
- 阿里巴巴筆試題阿里筆試
- 後端小白的VUE入門筆記, 前端高能慎入後端Vue筆記前端
- 前端筆試題面試題記錄前端筆試面試題
- 荔枝FM的前端筆試題前端筆試
- 各大網際網路公司2014前端筆試面試題–JavaScript篇前端筆試面試題JavaScript
- 前端筆試題面試題記錄(下)前端筆試面試題
- 各大網際網路公司2014前端筆試面試題–HTML,CSS篇前端筆試面試題HTMLCSS
- 阿里巴巴公司DBA筆試題阿里筆試
- 測試面試題目求解答面試題
- BAT及各大網際網路公司2014前端筆試面試題:JavaScript篇BAT前端筆試面試題JavaScript
- 線上問題排查,一不小心踩到阿里的 arthas坑了阿里
- 前端面試&筆試&錯題指南(三)前端面試筆試
- 前端面試&筆試&錯題指南(四)前端面試筆試
- 前端面試&筆試&錯題指南(二)前端面試筆試
- BAT及各大網際網路公司2014前端筆試面試題:HTML/CSS篇BAT前端筆試面試題HTMLCSS
- 【筆試技巧】碰到遊戲設計題型怎麼解答?有哪些思路?筆試遊戲設計
- 2016微軟4月線上筆試題微軟筆試
- 人工智慧:風口之上泡沫之中謹慎入坑人工智慧
- 前端高頻筆試題之HTML/CSS部分前端筆試HTMLCSS
- 用Python解答ProjectEuler問題(1)PythonProject
- C# 面試問題與解答1C#面試
- 一道前端面試題?求大神解答前端面試題
- 前端筆試題面試題記錄(上)| 掘金技術徵文前端筆試面試題
- Swift面試題收集和個人解答(長期更新)Swift面試題
- 關於一道前端筆試題的思考前端筆試
- 社招中級前端筆試面試題總結前端筆試面試題
- 2014年亞馬遜線上筆試題目及解法_9_24(字串編輯距離升級版)亞馬遜筆試字串
- AI筆試面試題庫-Python題目解析1AI筆試面試題Python
- web前端工程師面試題10條必會筆試題Web前端工程師面試題筆試
- 阿里春招前端面試(1)阿里前端面試
- 近期前端效能測試採坑總結前端