2019年 -- 最新前端面試題攻略


一、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…

 



鏈接:https://juejin.im/post/5c7f5923f265da2dd218f195


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM