天天看點

2016年BAT公司常見的Web前端面試題整理

1.JavaScript是一門什麼樣的語言,它有哪些特點?

沒有标準答案。

2.JavaScript的資料類型都有什麼?

基本資料類型:String,boolean,Number,Undefined

引用資料類型:Object(Array,Date,RegExp,Function,Null)

那麼問題來了,如何判斷某變量是否為數組資料類型?

  • 方法一.判斷其是否具有“數組性質”,如slice()方法。可自己給該變量定義slice方法,故有時會失效
  • 方法二.obj instanceof Array 在某些IE版本中不正确
  • 方法三.方法一二皆有漏洞,在ECMA Script5中定義了新方法Array.isArray(), 保證其相容性,最好的方法如下:  
if(typeof Array.isArray==="undefined")
{
  Array.isArray = function(arg){
        return Object.prototype.toString.call(arg)==="[object Array]"
    };  
}
      

3.已知ID的Input輸入框,希望改變文本框的背景顔色,怎麼做?(原生JS)

document.getElementById("id").style.backgroundColor = "red";
      

4.希望擷取到頁面中所有的checkbox怎麼做?(原生JS)

var domList = document.getElementsByTagName(‘input’)
var checkBoxList = [];
var len = domList.length;  //緩存到局部變量
while (len--) {  //使用while的效率會比for循環更高
  if (domList[len].type == ‘checkbox’) {
      checkBoxList.push(domList[len]);
  }
}      

5.Html事件綁定有幾種方式?

  •  直接在DOM裡綁定事件:<div onclick=”test()”></div> 這種方式稱為原生事件或者屬性事件
  •  在JS裡通過onclick綁定:xxx.onclick = test
  •  Dom标準通過事件添加進行綁定:addEventListener("click",test, false) //第三個參數為是否支援事件捕捉
  • IE事件:attachEvent("onclick",test)

那麼問題來了,Javascript的事件流模型都有什麼?

  • “事件捕捉”:事件由最不具體的節點先接收,然後逐級向下,一直到最具體的
  • 目标事件
  • “事件冒泡”:事件開始由最具體的元素接受,然後逐級向上傳播
  • “DOM事件流”:三個階段:事件捕捉,目标階段,事件冒泡
  • IE事件流:目标事件和事件冒泡

阻止事件冒泡的方式:

stopPropagation : function(ev) {
      if (ev.stopPropagation) {
            ev.stopPropagation();
      } else {
            ev.cancelBubble = true;
      }
},      

阻止事件的預設行為:

preventDefault : function(event) {
            if (event.preventDefault) {
                event.preventDefault();
            } else {
                event.returnValue = false;
            }
}      

6.看下列代碼,将會輸出什麼?(變量聲明提升)

var a=1;
function a(){}
alert(a);//列印1      

上面的代碼經過變量提升後,等價于下面的代碼

var a;function a(){}
a = 1;//隻把聲明提到最前面,指派a=1;保留,函數聲明也會提到最前面
alert(a);//列印      

再看下面的輸出結果:

var a=1;
var a=function (){}
alert(a);//列印a函數      

此時列印a函數,不會列印1,因為下面是一個函數表達式,跟變量聲明一樣,隻會把var a;提升到最前面,a=function(){}保留,會覆寫前面的a=1;是以列印函數。

此題目,我再百度面試的時候問到過。

7.掌握樣式的優先級。

!important > style(内聯) > Id(權重100) > class(權重10) > 标簽(權重1) 同類别的樣式,後面的會覆寫前面的。

百度視訊部門一道面試題是這樣的:

<style>
.red{color:red;}
.blue{color:blue;}
</style>

<p class="blue red"></p>
<!-- 此時顯示藍色,樣式的顯示跟class裡面的先後順序無關,都是類選擇器,後面的會覆寫前面的,是以藍色覆寫紅色的 -->      

8.怎樣添加、移除、移動、複制、建立和查找節點

1)建立新節點

createDocumentFragment()    //建立一個DOM片段

createElement()   //建立一個具體的元素

createTextNode()   //建立一個文本節點

2)添加、移除、替換、插入

appendChild()      //添加

removeChild()      //移除

replaceChild()      //替換

insertBefore()      //插入

3)查找

getElementsByTagName()    //通過标簽名稱

getElementsByName()     //通過元素的Name屬性的值

getElementById()        //通過元素Id,唯一性

9.用js寫一個正則比對标簽中是否包含一個class(百度面試題)

function hasClassName(id,name){
    var cls = document.getElementById(id).className;
    var reg = new RegExp("(^|\\s)"+name+"($|\\s)","g")
    return reg.test(cls);
}
//正則的意思是:以名字開頭或者以空格開頭,最終以名字結束或者以空格結束。      

10.事件循環綁定,輸出結果(考察閉包)

var list = document.getElementsByTagName("a");//假設有10個a
for(var i=0;i<list.length;i++){
    list[i].onclick = function(i){
        return function(){
            alert(i);
        }
    }
}
//最終點選的時候,都列印10      

通過閉包封裝後的代碼:

var list = document.getElementsByTagName("a");
for(var i=0;i<list.length;i++){
    list[i].onclick = (function(i){
        return function(){
            alert(i);
        }
    })(i)
}
//列印對應的索引      

閉包我所知道的兩個作用:

a.通過閉包可以把局部變量傳遞出來,就是通過閉包可以通路函數内部的變量,比如下面的代碼:

function count(){
     var num = 1;
     return function(){
      
           return num++;
    } 

}
var countFn = count();
countFn();//輸出1
countFn();//輸出2
countFn();//輸出3
countFn();//輸出4      

通過閉包就可以通路函數内部的局部變量,并且實作數量累加。

b.使用閉包可以避免空間污染,閉包内部的變量都隻能在内部使用,這樣有效避免和外部變量的混淆。(個人了解)

11.js數組去重。

var arr = [1,6,3,9,4,9,3,8,2];
var obj = {},newArr = [];
function delRepeat(){
    for(var i=0,j=arr.length;i<j;i++){
        if(!obj[arr[i]]){
            newArr.push(arr[i]);
            obj[arr[i]] = arr[i];
        }
    }
}

delRepeat();//删掉重複項
newArr//列印新數組      

12.兩個div标簽,如何控制标簽左邊固定,右邊自适應,左邊div标簽的寬度為100px(滴滴面試題)

//a. 左邊左浮動,右邊加個overflow:hidden;
       #lt{ float: left;width:100px; background: #ff0;}
       #rt{ overflow: hidden; background: #f0f;}
//b.左邊左浮動,右邊加個margin-left;
       #lt{ float: left; width:100px; background: #ff0;}

//以上兩種方式都可以實作      

滴滴面試起初問我,現在有并排的三個Div框,如何實作三個div都自适應,我當時就懵了,這個考察的是display:table的使用

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8"/>
    <title>等高布局</title>
    <style>
        html {
            font-size: 10px;;
        }
        body {
            font-size: 1.4rem;
        }
        .box {
            background-color: rgba(200,200,200,0.7);
            margin: 0 1rem;
            width: 33.33%;
            padding: 1rem;
        }
        .box:nth-child(2) {
            height: 5rem;
            background-color: rgba(200,210,230,0.7);
        }
        .accordant {
            display: table-row;
        }
        .table {
            width: 100%;
            display: table;
        }
        .table .accordant {
            display: table-row;
        }
        .table .accordant .box {
            display: table-cell;
            vertical-align: middle;
            text-align: center;
        }
    </style>
</head>
<body>
<div class="table">
    <div class="accordant">
        <div class="box">
            <p>這是一個 Figure</p>
        </div>
        <div class="box">
            <p>這是一個 Figure</p>
        </div>
        <div class="box">
            <p>這是一個 Figure</p>
        </div>
    </div>
</div>
</body>
</html>      

13.實作一個函數clone,可以對JavaScript中的5種主要的資料類型(包括Number、String、Object、Array、Boolean)進行值複制

  • 考察點1:對于基本資料類型和引用資料類型在記憶體中存放的是值還是指針這一差別是否清楚
  • 考察點2:是否知道如何判斷一個變量是什麼類型的
  • 考察點3:遞歸算法的設計
// 方法一:
Object.prototype.clone = function(){
        var o = this.constructor === Array ? [] : {};
        for(var e in this){
                o[e] = typeof this[e] === "object" ? this[e].clone() : this[e];
        }
        return o;
}
 
    //方法二:
    function clone(Obj) {   
        var buf;   
        if (Obj instanceof Array) {   
            buf = [];                    //建立一個空的數組 
            var i = Obj.length;   
            while (i--) {   
                buf[i] = clone(Obj[i]);   
            }   
            return buf;    
        }else if (Obj instanceof Object){   
            buf = {};                   //建立一個空對象 
            for (var k in Obj) {           //為這個對象添加新的屬性 
                buf[k] = clone(Obj[k]);   
            }   
            return buf;   
        }else{                         //普通變量直接指派
            return Obj;   
        }   
    }      

14.繼承的使用

function Animal(name) {
    this.name = name;
    this.showName = function() {
        console.log(this.name);
    };
}
//第一種繼承方式
function Cat(name) {
    Animal.call(this, name);//此處注意,call不能繼承對象原型上的方法
}
//第二種繼承方式
Cat.prototype = new Animal();//繼承所有屬性和方法

function Dog(name) {
    Animal.apply(this, name);//同Call一樣
}
Dog.prototype = new Animal();      

15.請評價以下代碼并給出改進意見

if(window.addEventListener){
    var addListener = function(el,type,listener,useCapture){
        el.addEventListener(type,listener,useCapture);
  };
}
else if(document.all){
    var addListener = function(el,type,listener){
        el.attachEvent("on"+type,function(){
          listener.apply(el);
      });
   }  
}      

評價:

  •  不應該在if和else語句中聲明addListener函數,應該提前先聲明,定義全局變量;
  •  不需要使用window.addEventListener或document.all來進行檢測浏覽器,應該使用能力檢測;
  •  由于attachEvent在IE中有this指向問題,是以調用它時需要處理一下

改進如下:

function addEvent(elem, type, handler){
  if(elem.addEventListener){
    elem.addEventListener(type, handler, false);
  }else if(elem.attachEvent){
           elem.attachEvent('on' + type, handler);
  }else{
       elem['on' + type] = handler;
      }
}      

16.對作用域上下文和this的了解,看下列代碼:

var User = {
  count: 1,
 
  getCount: function() {
    return this.count;
  }
};
 
console.log(User.getCount());  // 1
 
var func = User.getCount;
console.log(func());  // undefined