標籤:

記一次前端面試

之前找工作總是「沒心沒肺」,總覺得自己可以的,除了簡歷,基本沒準備過面試題。這次真是被面的體無完膚,深刻認識到基礎的重要性,大體總結一下經歷過的面試題,簡單梳理一下。

首先,如果面試的是前端,需要深刻認識的一點是,考察範圍為html|css|js(es6),所以node,java等後台語言不必過多糾結,如果有相關項目那當然是甚好。接下來就基礎方向總結一下。

首先css方向

1.盒模型

盒模型有兩種,標準模型(box-sizing:content-box)和IE模型(box-sizing:border-box)。假設頁面有一個div,其樣式如下:

div { width: 50px; height: 50px; background: #ff00ff; border: 1px solid #ffff00; padding: 20px 10px; margin: 20px;}

標準模型下,盒子的寬度為50px+(1*2)px+(10*2)px=72px,高度為50px+(1*2)px+(20*2)px=92px,也就是默認把border和padding算在了盒子最後的寬高內。

IE模型下,盒子的寬度為50px,高度為50px,也就是在某一方向的(padding+border)*2小於盒子的width時,最後的寬高依然等於盒子原始的width和height,如果某一方向的(padding+border)*2大於盒子的width時,此時寬高計算方式為(padding+border)*2。

除了模型本身外需要關注的一點就是margin。如果盒子是上下結構,則之間的間距為擁有較大margin的盒子,如果是左右結構,則間距為兩個盒子的margin值相加。

2.BFC

BFC(Block formatting context)直譯為"塊級格式化上下文"。最大的特點為它是一個獨立的渲染區域,並且與這個區域外部毫不相干。這個話題可以由盒模型中上下margin重疊的問題引出。觸發BFC的方式如下

float的值不為none

position的值不為static或者relative

display的值為 table-cell, table-caption, inline-block, flex, inline-flex

overflow的值不為visible

通常我喜歡的方式為浮動,display:inline-block和overflow:hidden。可以通過一個例子來理解BFC的獨立性,如下所示

<style> p{ margin: 30px; height: 20px; line-height: 20px; background: red; }</style><p>我是p1</p><p>我是p2</p>

兩個塊級元素p設置了margin為30px,此時可能我們的需求為上下間距(30px+30px),這種情況就可以通過創建BFC解決,代碼如下:

<style> div{ overflow: hidden; } p{ margin: 30px; height: 20px; line-height: 20px; background: red; }</style><div> <p>我是p1</p></div><p>我是p2</p>

我們為第一個p標籤外層加了一個div,並且樣式為overflow:hidden;也就創建了一個BFC盒子,此時兩個p標籤的間距就變為了第一個p標籤在所屬的BFC內的底部margin值30px加上第二個p標籤距離頂部的margin值30px,最終也就變為了60px。

3.水平垂直居中(盒子寬高可以隨意更改,也就是盒子寬高不固定的居中方式)

方法1:(通過定位,外層和內層盒子寬高都不固定)

<style> div{ position: relative; } .inner{ position: absolute; margin: auto; top: 0; left: 0; right: 0; bottom: 0; }</style><div> <div class="inner"> </div></div>

方法2:(table-cell)

<style> div{ display: table-cell; vertical-align: middle; text-align: center; } .inner{ vertical-align: middle; display: inline-block; }</style><div> <div class="inner"> </div></div>

方法3:(flex)

<style> div{ display: flex; align-items: center; justify-content: center; }</style><div> <div class="inner"> </div></div>

方法4:(translate)

<style> div{ position: relative; } .inner{ position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }</style><div> <div class="inner"> </div></div>

4.移動端rem

首先1rem的值為頁面根節點html的font-size值。移動端為了適配不同機型,所以通常會採用rem來定義頁面節點尺寸。定義方式通常有兩種,第一種:通過js來控制;第二種:通過css媒體查詢來控制。兩種方式各有優缺點。通過js來控制,會把瀏覽器寬度分割成制定的份數,每份定義為1rem,這樣做的好處是能比較精確的控制元素尺寸,但是也有缺點,就是需要提前載入這段適配js,不可避免會導致白屏時間。第二種方式首先是直接載入的,但是媒體查詢的精確度就不是很高了,通常我們都是通過比例給出一個合適的值。

再來看看js的

1.閉包

最常見的例子為下列兩個,代碼如下:

for(var i=0,l=5;i<l;i++){ setTimeout(function(i){ console.log(i); // 5,5,5,5,5 },0)}// 改寫成正常輸出for(var i=0,l=5;i<l;i++){ (function a(i){ setTimeout(function(){ console.log(i); // 0,1,2,3,4 },0) })(i) }

2.this指針

var name = 1;var util = { name: 2, getName: function(){ return this.name; }, sub: { name: 3, getName: function(){ console.log(this); return this.name } }}var a = util.getName;var b = util.sub;console.log(a()); // 1 a的this為window,所以為window.nameconsole.log(util.getName()); // 2 util.name為2console.log(b.getName()); // 3 // b的this為sub,sub.name = 3console.log(util.sub.getName()); // 3 getName為sub的直接調用,所以也為sub.name

通常意義上this指針指向為最後調用它的對象。這裡需要注意的一點就是如果返回值是一個對象,那麼this指向的就是那個返回的對象,如果返回值不是一個對象那麼this還是指向函數的實例,例子如下:

function getName(){ this.name = 1; return {}; // 返回對象}var a = new getName; console.log(a.name); //undefinedfunction getName(){ this.name = 1; return 2; // 返回非對象}var d = new getName; console.log(d.name); //1

3.事件

事件分為捕獲和冒泡,阻止默認和阻止冒泡都是有兼容性的,兼容代碼如下:

function preventDefa(e){ if(window.event){ //IE中阻止函數器默認動作的方式 window.event.returnValue = false; }else{ //阻止默認瀏覽器動作(W3C) e.preventDefault(); } } function stopBubble(e) { if(e && e.stopPropagation) { //非IE e.stopPropagation(); } else { //IE window.event.cancelBubble = true; } }

其次為原生事件的兼容,代碼如下:

function addEvent(){ var arg0 = arguments[0], arg1 = arguments[1], arg2 = arguments[2]; if (arg0.addEventListener) { arg0.addEventListener(arg1, arg2, false); }else if(arg0.attachEvent) { // ie arg0.attachEvent(on + arg1, arg2); }else{ arg0[on + arg1] = arg2; }};

5.原型鏈

function Parent(){ this.name = james;}Parent.prototype.getName = function () { console.log(this.name);}var newPeople = new Parent();function Son(){ // 繼承靜態方法 Parent.call(this);}// 繼承原型Son.prototype = new Parent().__proto__;// 修復指向Son.prototype.constructor = Son;// 下列4個均為trueconsole.log( newPeople.__proto__ === Parent.prototype ); console.log( Parent.prototype.__proto__ === Object.prototype );console.log( newPeople instanceof Parent );console.log( newPeople instanceof Object );

首先子類繼承父類需要從靜態方法和原型鏈兩層上實現繼承。通過call引用了父類的this,在原型掛載時需要注意指嚮應該是一個父類的實例,而不是直接Parent.prototype,存在引用問題。當指向實例後需要注意prototype上默認掛載的constructor屬性需要修正到子類構造函數上。

在例子的下方有4句console,前兩句展示了原型鏈的含義,最終指向為Object對象。後兩句闡述了instanceof的含義,即判斷一個構造函數的prototype屬性所指向的對象是否存在另外一個要檢測對象的原型鏈上。

6.call,apply,bind

首先這3個都是用來改變this指針用的,call和apply是立即執行,bind只是為綁定,需要調用才會執行,call和apply的參數形式也有所不同call的第二個參數為列舉的一個個參數,apply為數組。面試中有問怎麼實現一個bind方法,也就是只綁定this指向,簡單實現代碼如下:

Function.prototype.bind = function(that){ var _this = this, args = Array.prototype.slice.call(arguments,1); return function(){ return _this.apply(that,args) } }

思路:首先認識到bind為Function下的方法,其次拿到參數,最後由於需要執行才有效,所以返回一個函數。

除了這些外接下來基本考察的就是數組了(對象考察較少),這裡列舉幾個

1.數組去重

new Set([...arr])

es5實現方式為

function unique(arr) { var n = []; for (var i = 0; i < arr.length; i++) { if (n.indexOf(arr[i]) == -1) n.push(arr[i]); } return n;}

2.判斷是否為數組

Object.prototype.toString.call(arr)==[object Array]

3.取出兩個數組的相同項

let arr1 = [1,3,4,5];let arr2 = [1,4,6];let getSome = arr1.filter(item=>{ return arr2.includes(item)});console.log(getSome); // [1,4]

以上為基礎部分考察最多的地方,除此之外還有一些其它問題,這裡簡單羅列下:

1.css3實現一個三角形,實現原理是什麼;

2.css3透明opacity,以及避免影響子元素的rgba表示方式,還有ie的hack方式;

3.js幀動畫,如果為定時器,則為每秒60幀動畫最流暢;

4.求一個數組的最大連續子集,求一個數組的和最大的子集,二維數組遍歷如果採用從邊上環形繞圈的方式,也就是m*n數列arr,從arr[0][0]-arr[0][m]-a[n][m]-a[n][0]-a[1][0]...這樣等,所以數組這塊的內容需要多練習;

5.跨域原理和常見跨域方式;

6.函數柯粒化及其實現;

7.性能優化;

到這裡基本遍是基礎部分大多數的問題了。接下來說一下除了基礎外的部分內容

1.AMD,CMD,COMMON的區別和一些原理(例如怎麼實現的按需載入);

2.vue的原理以及生命周期,父子組件通信,vuex的原理;

3.react生命周期,父子組件通信;

4.vue雙向綁定原理;

5.對於構建工具的了解和常用的npm包有哪些;

6.對於es6的掌握程度,尤其如promise的理解等;

7.對於後台語言的接觸;

8.個人職業規劃或者最近幾年的規劃;

9.參照你的項目做一些提問,例如亮點,用到的技術棧等;

謹記基礎對於一場面試成功與否的重要性~

共勉~

推薦閱讀:

什麼是json jsonp 與ajax關係
Node手把手構建靜態文件伺服器
前端日刊-2017.12.25
未來兩年前端開發的趨勢是什麼?
實現符合 Promise/A+ 規範的Promise

TAG:前端開發 |