最新前端面試題攻略

晴天~ ☀發表於2019-03-06

一、html和css部分

1、如何理解CSS的盒子模型?

  • 每個HTML元素都是長方形盒子。 
  • (1)盒子模型有兩種:IE盒子模型、標準W3C盒子模型;IE的content部分包含了border和pading。 
  • (2)標準W3C盒模型包含:內容(content)、填充(padding)、邊界(margin)、邊框(border)。

2、用純 CSS 建立一個三角形的原理是什麼?

  • 把上、左、右三條邊隱藏掉
  • 顏色設為 transparent
  • #demo { width:0; height: 0; border-width: 20px; border-style: solid; border-color: transparent transparent red transparent; }

3、CSS3中translate、transform、translation和animation的區別

  • translate 移動 通過 translate() 方法,元素從其當前位置移動,根據給定的 left(x 座標) 和 top(y 座標) 位置引數:
  1. transform: translate(50px, 100px);
  2. -ms-transform: translate(50px,100px);
  3. -webkit-transform: translate(50px,100px);
  4. -o-transform: translate(50px,100px);
  5. -moz-transform: translate(50px,100px);
  • transform 改變、變形
  1. 旋轉:rotate() 順時針旋轉給定的角度,允許負值 rotate(30deg)
  2. 扭曲:skew() 元素翻轉給定的角度,根據給定的水平線(X 軸)和垂直線(Y 軸)引數:skew(50deg,20deg)
  3. 縮放:scale() 放大或縮小,根據給定的寬度(X 軸)和高度(Y 軸)引數: scale(2,4)
  4. 移動:translate() 平移,傳進 x,y值,代表沿x軸和y軸平移的距離
  • animation 動畫 語法 animation: name duration timing-function delay iteration-count direction;
  1. animation-name 規定需要繫結到選擇器的 keyframe 名稱。。
  2. animation-duration 規定完成動畫所花費的時間,以秒或毫秒計。
  3. animation-timing-function 規定動畫的速度曲線。
  4. animation-delay 規定在動畫開始之前的延遲。
  5. animation-iteration-count 規定動畫應該播放的次數。
  6. animation-direction 規定是否應該輪流反向播放動畫。

4、使用flex佈局使一個div水平垂直局中

父級:#container{
    display:flex;
    justify-content:center;
    align-items: center;
    width: 200px;
    height: 200px;
}
子級:#center{
    width: 100px;
    height: 100px;
    background: red;
}
複製程式碼

5、使用過flex佈局嗎?flex-grow和flex-shrink屬性的作用是什麼? 

  • flex-grow: 屬性決定了父元素在空間分配方向上還有剩餘空間時,如何分配這些剩餘空間。其值為一個權重(也稱擴張因子),預設為 0(純數值,無單位),剩餘空間將會按照這個權重來分配。  
  • flex-shrink:這個屬性其實就是定義一個子容器的壓縮比例(當父容器放不下子容器時,不會自動換行,每個子容器會適當的壓縮,這個值就是設定壓縮的比例的)。他的預設值是1

二、js程式碼面試題

1、陣列slice()和splice()方法的區別

  • slice() 方法:可從已有的陣列中返回選定的元素。slice(開始擷取位置,結束擷取位置)

var movePos=[11,22,33];
var arr=movePos.slice(1,2);
document.write(arr)  //返回擷取的元素:[22]
document.write(arr.length)  //返回陣列長度1,擷取的陣列的長度複製程式碼

  • splice() :方法向/從陣列中新增/刪除專案,然後返回被刪除的專案。

var movePos=[11,22,33,44];
var arr=movePos.splice(1,2);//movePos.splice(開始刪除的下表位置,刪除陣列元素的個數);
document.write(arr) ; //返回新的陣列:[22,33]
11document.write(arr.length) ;//返回陣列長度2複製程式碼

splice() 方法可刪除從 index 處開始的零個或多個元素,並且用引數列表中宣告的一個或多個值來替換那些被刪除的元素。

var movePos =[111,222,333,444];    
movePos.splice(2,1,"666")
//movePos.splice(開始刪除的下表位置,刪除陣列元素的個數,向陣列新增的新專案。);
//從下標2開始刪除一位,並用666替換刪除下表位置的元素複製程式碼

2、實現add(3)(4)和add(3,4)都輸出7,請實現add方法

function add(x,y){
	var sum = x;
    if(y){
        return (sum + y);
    }
    else
    {
        var add2 = function(z){
            return (sum + z);
        }
        return add2;
    }
} 複製程式碼

but這個方法不能擴充套件成add(3)(4)(5)...和add(3,4,5...)都輸出他們的和,歡迎大家評論區留言,寫一個擴充套件後的。

3、求n的階乘值n!?

  • 方案一:利用while迴圈

function factorial(num){
    var result = 1;
    while(num){
        result *= num;
        num--;
    }
    return result;
}複製程式碼

  • 方案二:使用遞迴

function factorial(num){
    if(num <= 0){
        return 1;
    }else{
        return num*arguments.callee(num-1);
    }
}複製程式碼

4、求1234567890.32格式化為:1,234,567,890.32。

  • 方法一:利用字串擷取的方法

function formatNumber(str) {
    let arr = [];
    let lastStr = str.substring(str.indexOf('.'));
    let formatStr = str.substring(0,str.indexOf('.'))
    let count = formatStr.length
    while (count >= 3) {
        arr.unshift(formatStr.slice(count - 3, count))
        count -= 3
    }
    // 如果是不是3的倍數就另外追加到上去
    formatStr.length % 3 && arr.unshift(formatStr.slice(0, formatStr.length % 3))
    return arr.toString()+lastStr;
}複製程式碼

  • 方法二:使用reduce函式

function formatNumber(str) {
    let lastStr = str.substring(str.indexOf('.'));
    let formatStr = str.substring(0,str.indexOf('.'))
    // ["0", "9", "8", "7", "6", "5", "4", "3", "2", "1"]
    return formatStr.split("").reverse().reduce((prev, next, index) => {
        return ((index % 3) ? next : (next + ',')) + prev
    })+lastStr;
}複製程式碼

5、評價一下三種方式實現繼承的有缺點並改進;

function Animal(){}
function Cat(){}
方法1:
Cat.prototype = new Animal();方法2:
Cat.ptototype = Animal.prototype;方法3:
Cat.prototype = Object.create(Animal.prototype);複製程式碼

方法1:

  • 優點
  1. 正確設定原型鏈實現繼承
  2. 父類例項屬性得到繼承,原型鏈查詢效率提高,也能為一些屬性提供合理的預設值
  • 缺點
  1. 父類例項屬性為引用型別時,不恰當地修改會導致所有子類被修改 
  2. 無法傳遞引數

方法二:

  • 優點
  1. 正確設定原型鏈實現繼承
  • 缺點
  1. 父類建構函式原型與子類相同。修改子類原型新增方法會修改父類

方法三:

  • 優點
  1. 正確設定原型鏈且避免方法1.2中的缺點
  • 缺點
  1. ES5方法需要注意相容性

改進:

  • 所有三種方法應該在子類建構函式中呼叫父類建構函式實現例項屬性初始化

function Cat() {    
    Animal.call(this);
}複製程式碼

  • 封裝一個原型繼承的方法

function extend(Child, Parent) {
    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    //用新建立的物件替代子類預設原型,設定Rect.prototype.constructor = Rect;保證一致性
    Child.prototype.constructor = Child;  
}複製程式碼

6、寫出下列程式碼執行的輸出值

var a = 100;
 function test(){
    alert(a);
    var a = 10;
    alert(a);
}
test();複製程式碼

輸出:undefined,10

var a = 100;
 function test(){
    alert(a);
    var a = 10;
    alert(a);
}
test();複製程式碼

輸出:undefined,10

var a = 100;
function test2(){
    alert(a);
    let a = 10;
    alert(a);
}複製程式碼

輸出:報錯 a is not defined,10

alert(3>2>1);複製程式碼

輸出:false 3>2是true,隱式型別轉換,變成1,1>1肯定是false啦

 7、談一談JavaScript作用域鏈

  • 當執行一段JavaScript程式碼(全域性程式碼或函式)時,JavaScript引擎會建立為其建立一個作用域又稱為執行上下文(Execution Context),在頁面載入後會首先建立一個全域性的作用域,然後每執行一個函式,會建立一個對應的作用域,從而形成了一條作用域鏈。每個作用域都有一條對應的作用域鏈,鏈頭是全域性作用域,鏈尾是當前函式作用域。
  • 作用域鏈的作用是用於解析識別符號,當函式被建立時(不是執行),會將this、arguments、命名引數和該函式中的所有區域性變數新增到該當前作用域中,當JavaScript需要查詢變數X的時候(這個過程稱為變數解析),它首先會從作用域鏈中的鏈尾也就是當前作用域進行查詢是否有X屬性,如果沒有找到就順著作用域鏈繼續查詢,直到查詢到鏈頭,也就是全域性作用域鏈,仍未找到該變數的話,就認為這段程式碼的作用域鏈上不存在x變數,並丟擲一個引用錯誤(ReferenceError)的異常。

8、如何理解JavaScript原型鏈

  • JavaScript中的每個物件都有一個__proto__屬性(函式物件即有__proto__,又有prototype,prototype指向自己的原型而__proto__指向父級的原型)我們稱之為原型,而原型的值也是一個物件,因此它也有自己的原型,這樣就串聯起來了一條原型鏈,原型鏈的鏈頭是Object.prototype.__proto_,它的值比較特殊,值為null。
  • 原型鏈的作用是用於物件繼承,函式A的原型屬性(prototype property)是一個物件,當這個函式被用作建構函式來建立例項時,該函式的原型屬性將被作為原型賦值給所有物件例項,比如我們新建一個陣列,陣列的方法便從陣列的原型上繼承而來。
  •  當訪問物件的一個屬性時, 首先查詢物件本身, 找到則返回; 若未找到, 則繼續查詢其原型物件的屬性(如果還找不到實際上還會沿著原型鏈向上查詢, 直至到根). 只要沒有被覆蓋的話, 物件原型的屬性就能在所有的例項中找到,若整個原型鏈未找到則返回undefined;

9、js閉包

  • 閉包,官方對閉包的解釋是:一個擁有許多變數和繫結了這些變數的環境的表示式(通常是一個函式),因而這些變數也是該表示式的一部分。
  • 閉包的特點:
  1. 作為一個函式變數的一個引用,當函式返回時,其處於啟用狀態。
  2. 一個閉包就是當一個函式返回時,一個沒有釋放資源的棧區。
  簡單的說,Javascript允許使用內部函式---即函式定義和函式表示式位於另一個函式的函式體內。而且,這些內部函式可以訪問它們所在的外部函式中宣告的所有區域性變數、引數和宣告的其他內部函式。當其中一個這樣的內部函式在包含它們的外部函式之外被呼叫時,就會形成閉包。

10、js為什麼是單執行緒語言,怎麼模擬多執行緒

  • JavaScript的單執行緒,與它的用途有關。作為瀏覽器指令碼語言,JavaScript的主要用途是與使用者互動,以及操作DOM。這決定了它只能是單執行緒,否則會帶來很複雜的同步問題。比如,假定JavaScript同時有兩個執行緒,一個執行緒在某個DOM節點上新增內容,另一個執行緒刪除了這個節點,這時瀏覽器應該以哪個執行緒為準?
  • 為了利用多核CPU的計算能力,HTML5提出Web Worker標準,允許JavaScript指令碼建立多個執行緒,但是子執行緒完全受主執行緒控制,且不得操作DOM。所以,這個新標準並沒有改變JavaScript單執行緒的本質。

11、const a = 1 a = 2 這樣會報錯,但是 對於複合型別來說 const foo = {a:1} foo.a = 2 這樣就不會報錯,為什麼?

  • 複合型別的變數,變數名不指向資料,而是指向資料所在的地址。const命令只是保證變數名指向的地址不變,並不保證該地址的資料不變,所以將一個物件宣告為常量必須非常小心。

以下是其它面試題的詳細

1、深拷貝和淺拷貝

juejin.im/post/5c400a…

2、Object.defineProperty()的用法 

juejin.im/post/5c3870…

3、JS實現AOP 面向切面程式設計 

juejin.im/post/5c3865…

4、http請求頭以及響應頭詳解

juejin.im/post/5c17d3…

5、瀏覽器輸入一個網址回車後,發生了什麼

juejin.im/post/5c1c52…

6、call,apply和bind模擬實現

juejin.im/post/5c7fe2…


相關文章