前端面試知識點總結

這篇文章是對我大四秋招以來面試的總結,裏面包含前端面試知識的方方面面,目前本人已經拿到騰訊offer,希望能對後面找工作的學習學妹們有所幫助。


騰訊面試對基礎比較看重,然後需要你有兩三個比較好的項目,一面重視面試者對前端基礎的把握,還要手寫代碼,不過不難,二面部門的leader面,這一面比較難,面試官會對你的項目細節進行深挖,所以說項目要牛逼一點,最後還會有一道邏輯題(我沒有答上來),三面是HR面,如果你想進大公司的話,下面這些技術是肯定要掌握的:html5,css3,JavaScript,略懂一點jQuery源碼,Node.js,express,mongoose,數據庫mongodb。大公司問的核心在於JavaScript。如果下面的知識點你都可以打上來,恭喜你拿下bat不是問題----------------- --2016-11-11寫


轉載請註明出處,碼這麼多字不容易。


一、html+css部分、


(1)css盒模型,可能會要求手寫一個佈局,這個佈局基本上用到的css是margin的負值,boxing-sizing:border-box,佈局儘量往這方面想。瀏覽器佈局的基本元素是盒,在w3c的標準模式下,width=width,但是在怪異模式下,width=border*2+padding*2+width;其中後代元素的width:100%;參照的是右邊的那個width,




(2)html5的新特性




1、標籤語義化,比如header,footer,nav,aside,article,section等,新增了很多表單元素,入email,url等,除去了center等樣式標籤,還有除去了有性能問題的frame,frameset等標籤




2、音視頻元素,video,audio的增加使得我們不需要在依賴外部的插件就可以往網頁中加入音視頻元素。




3、新增很多api,比如獲取用戶地理位置的window.navigator.geoloaction,




4、websocket




websocket是一種協議,可以讓我們建立客戶端到服務器端的全雙工通信,這就意味着服務器端可以主動推送數據到客戶端,




5、webstorage,webstorage是本地存儲,存儲在客戶端,包括localeStorage和sessionStorage,localeStorage是持久化存儲在客戶端,只要用戶不主動刪除,就不會消失,sessionStorage也是存儲在客戶端,但是他的存在時間是一個回話,一旦瀏覽器的關於該回話的頁面關閉了,sessionStorage就消失了,




6、緩存




html5允許我們自己控制哪些文件需要緩存,哪些不需要,具體的做法如下:




1、首先給html添加manifest屬性,並賦值爲cache.manifest
2、cache.manifest的內容爲: 
         CACHE MANIFEST
         #v1.2
         CACHE :           //表示需要緩存的文件
           a.js
           b.js
       NETWORK:    //表示只在用戶在線的時候才需要的文件,不會緩存
         c.js
       FALLBACK
       /        /index.html     //表示如果找不到第一個資源就用第二個資源代替
7、web worker,web worker是運行在瀏覽器後臺的js程序,他不影響主程序的運行,是另開的一個js線程,可以用這個線程執行復雜的數據操作,然後把操作結果通過postMessage傳遞給主線程,這樣在進行復雜且耗時的操作時就不會阻塞主線程了。




(3)對html5的語義話的理解




html5的語義化指的是用正確的標籤包含正確的內容,比如nav標籤,裏面就應該包含導航條的內容,而不是用做其他的用途,標籤語義化的好處就是結構良好,便於閱讀,方便威化,也有利於爬蟲的查找,提高搜索率。




(4)cookie,sessionStorage,localeStorage的區別




cookie是存儲在瀏覽器端,並且隨瀏覽器的請求一起發送到服務器端的,它有一定的過期時間,到了過期時間自動會消失。sessionStorage和localeStorage也是存儲在客戶端的,同屬於web Storage,比cookie的存儲大小要大有8m,cookie只有4kb,localeStorage是持久化的存儲在客戶端,如果用戶不手動清除的話,不會自動消失,會一直存在,sessionStorage也是存儲在客戶端,但是它的存活時間是在一個回話期間,只要瀏覽器的回話關閉了就會自動消失。




(5)多個頁面之間如何進行通信




使用cookie,使用web worker,使用localeStorage和sessionStorage




(6)瀏覽器的渲染過程




1、首先獲取html,然後構建dom樹




2、其次根據css構建render樹,render樹中不包含定位和幾何信息




3、最後構建佈局數,佈局是含有元素的定位和幾何信息




(7)重構、迴流




瀏覽器的重構指的是改變每個元素外觀時所觸發的瀏覽器行爲,比如顏色,背景等樣式發生了改變而進行的重新構造新外觀的過程。重構不會引發頁面的重新佈局,不一定伴隨着迴流,




迴流指的是瀏覽器爲了重新渲染頁面的需要而進行的重新計算元素的幾何大小和位置的,他的開銷是非常大的,迴流可以理解爲渲染樹需要重新進行計算,一般最好觸發元素的重構,避免元素的迴流;比如通過通過添加類來添加css樣式,而不是直接在DOM上設置,當需要操作某一塊元素時候,最好使其脫離文檔流,這樣就不會引起迴流了,比如設置position:absolute或者fixed,或者display:none,等操作結束後在顯示。




二、JavaScript部分




(1)JavaScript的數據類型




基本數據類型:Number,String,Boolean,Undefined,Null




複雜數據類型:Object,Array,Function,RegExp,Date,Error




全局數據類型:Math




(2)JavaScript的閉包




閉包簡單的說就是一個函數能訪問外部函數的變量,這就是閉包,比如說:




[javascript] view plain copy
  




a函數中的b函數就是閉包了,b函數可以使用a函數的局部變量,參數,最典型的閉包應該是下面這樣,將定義在函數中的函數作爲返回值




function a(x){
       var tem=3;
      function b(y){
          console.log(x+y+(++tem));
     }
return b;
}
閉包的另一種作用是隔離作用域,請看下面這段代碼




for(var i=0;i<2;i++){
      setTimeout(function(){
              console.log(i);
        },0);
}
上面這段代碼的執行結果是2,2而不是0,1,因爲等for循環出來後,執行setTimeout中的函數時,i的值已經變成了2,這就是沒有隔離作用域所造成的,請看下面代碼




for(var i=0;i<2;i++){
      (function(i){
             setTimeout(function(){
              console.log(i);
        },0)
    })(i);
}
這樣就會輸出0,1,我們的立即執行函數創建了一個作用域,隔離了外界的作用域,閉包的缺點是,因爲內部閉包函數可以訪問外部函數的變量,所以外部函數的變量不能被釋放,如果閉包嵌套過多,會導致內存佔用大,要合理使用閉包。




(3)new 操作符到底做了什麼




首先,new操作符爲我們創建一個新的空對象,然後this變量指向該對象,




其次,空對象的原型執行函數的原型,




最後,改變構造函數內部的this的指向




代碼如下:




var obj={};
obj.__proto__=fn.prototype;
fn.call(obj);
(4)改變函數內部this指針的指向函數




call和apply,假設要改變fn函數內部的this的指向,指向obj,那麼可以fn.call(obj);或者fn.apply(obj);那麼問題來了,call和apply的區別是什麼,其是call和apply的區別在於參數,他們兩個的第一個參數都是一樣的,表示調用該函數的對象,apply的第二個參數是數組,是[arg1,arg2,arg3]這種形式,而call是arg1,arg2,arg3這樣的形式。還有一個bind函數,




var bar=fn.bind(obj);那麼fn中的this就指向obj對象了,bind函數返回新的函數,這個函數內的this指針指向obj對象。




(5)JavaScript的作用域和作用域鏈




JavaScript的作用域指的是變量的作用範圍,內部作用域由函數的形參,實參,局部變量,函數構成,內部作用域和外部的作用域一層層的鏈接起來形成作用域鏈,當在在函數內部要訪問一個變量的時候,首先查找自己的內部作用域有沒有這個變量,如果沒有就到這個對象的原型對象中去查找,還是沒有的話,就到該作用域所在的作用域中找,直到到window所在的作用域,每個函數在聲明的時候就默認有一個外部作用域的存在了,比如:




var t=4;
function foo(){
       var tem=12;
      funciton bar(){
       var temo=34;
       console.log(t+" "+tem+" "+temo);
      }
}
bar找t變量的過程就是,先到自己的內部作用域中找,發現沒有找到,然後到bar所在的最近的外部變量中找,也就是foo的內部作用域,還是沒有找到,再到window的作用域中找,結果找到了




(6)JavaScript的繼承




function A(name){  this.name=name; }
A.prototype.sayName=function(){ console.log(this.name); }
function B(age){ this.age=age; }
原型繼承




B.prototype=new A("mbj");  //被B的實例共享
var foo=new B(18);
foo.age;    //18,age是本身攜帶的屬性
foo.name;   //mbj,等價於foo.__proto__.name
foo.sayName(); //mbj,等價於foo.__proto__.proto__.sayName()
foo.toString();  //"[object Object]",等價於foo.__proto__.__proto__.__proto__.toString();
這樣B通過原型繼承了A,在new B的時候,foo中有個隱藏的屬性__proto__指向構造函數的prototype對象,在這裏是A對象實例,A對象裏面也有一個隱藏的屬性__proto__,指向A構造函數的prototype對象,這個對象裏面又有一個__proto__指向Object的prototype




這種方式的缺第一個缺點是所有子類共享父類實例,如果某一個子類修改了父類,其他的子類在繼承的時候,會造成意想不到的後果。第二個缺點是在構造子類實例的時候,不能給父類傳遞參數。




構造函數繼承
function B(age,name){  this.age=age;A.call(this,name); }
var foo=new B(18,"wmy");
foo.name;     //wmy
foo.age;      //18
foo.sayName();   //undefined
採用這種方式繼承是把A中的屬性加到this上面,這樣name相當於就是B的屬性,sayName不在A的構造函數中,所以訪問不到sayName。這種方法的缺點是父類的prototype中的函數不能複用。




原型繼承+構造函數繼承




function B(age,name){  this.age=age;A.call(this,name); }
B.prototype=new A("mbj");
var foo=new B(18,"wmy");
foo.name;     //wmy
foo.age;      //18
foo.sayName();   //wmy
這樣就可以成功訪問sayName函數了,結合了上述兩種方式的優點,但是這種方式也有缺點,那就是佔用的空間更大了。




(7)JavaScript變量提升




請看下面代碼




var bar=1;
function test(){
  console.log(bar);     //undeifned
  var bar=2; 
  console.log(bar);  //2
}
test();
爲什麼在test函數中會出現上述結果呢,這就是JavaScript的變量提升了,雖然變量bar的定義在後面,不過瀏覽器在解析的時候,會把變量的定義放到最前面,上面的test函數相當於




function test(){
  var bar;
  console.log(bar);   //undefined
  bar=2; 
  console.log(bar);   //2
}
再看




var foo=function(){  console.log(1); }
function foo(){  console.log(2); }
foo();  //結果爲1
同樣的,函數的定義也會到提升到最前面,上面的代碼相當於
function foo(){  console.log(2); }
var foo;
foo=funciton(){ console.log(1); }
foo();   //1
(8)JavaScript事件模型




原始事件模型,捕獲型事件模型,冒泡事件模型,




原始事件模型就是ele.οnclick=function(){}這種類型的事件模型




冒泡事件模型是指事件從事件的發生地(目標元素),一直向上傳遞,直到document,




捕獲型則恰好相反,事件是從document向下傳遞,直到事件的發生地(目標元素)




IE是隻支持冒泡事件模型的,下面是兼容各個瀏覽器的事件監聽代碼




EventUtil={
  addListener:function(target,type,handler){
    if(target.addEventListener){
        target.addEventListener(type,handler);
    }else if(target.attachEvent){
        target.attach("on"+type,function(){
              handler.call(target);  //讓handler中的this指向目標元素
        });
    }else{
        target["on"+type]=handler;
    }
  },
 removeListener:function(target,type,handler){   
      if(target.removeEventListener){    
        target.removeEventListener(type,handler);          
     }else if(target.detachEvent){
        target.detachEvent("on"+type,handler);
     }else{
        target["on"+type]=null;
     }
  },
 getEvent:function(e){      //獲取事件對象
     var evt=window.event||e;
     return evt;
 },
 getTarget:function(e){      //獲得目標對象
     var evt=EventUtil.getEvent(e);
     var target;
     if(evt.target){ target=evt.target;}
     else {target=evt.srcElement;}
     return target;
 },
 stopPropagation:function(e){  //停止冒泡
     var evt=EventUtil.getEvent(e);
     if(evt.stopPropagation) {evt.stopPropagation();}
     else {evt.cancelBubble=true;}
 },
 preventDefault:function(e){   //阻值默認行爲的發生
     var evt=EventUtil.getEvent(e);
     if(evt.preventDefault){ evt.preventDefault(); }
     else {e.returnValue=false;}
 }
}
(9)內存泄漏




內存泄漏指的是瀏覽器不能正常的回收內存的現象




(10)瀏覽器的垃圾回收機制




垃圾收集器必須跟蹤哪個變量有用哪個變量沒用,對於不再有用的變量打上標記,以備將來收回其佔用的內存,內存泄露和瀏覽器實現的垃圾回收機制息息相關, 而瀏覽器實現標識無用變量的策略主要有下兩個方法:




第一,引用計數法




跟蹤記錄每個值被引用的次數。當聲明一個變量並將引用類型的值賦給該變量時,則這個值的引用次數就是1。如果同一個值又被賦給另一個變量,則該值的引用次 數加1.相反,如果包含對這個值引用的變量又取得另外一個值,則這個值的引用次數減1.當這個值的引用次數變成0時,則說明沒有辦法訪問這個值了,因此就 可以將其佔用的內存空間回收回來。




如: var a = {};     //對象{}的引用計數爲1
     b = a;          //對象{}的引用計數爲 1+1 
     a = null;       //對象{}的引用計數爲2-1
所以這時對象{}不會被回收;




IE 6, 7 對DOM對象進行引用計數回收, 這樣簡單的垃圾回收機制,非常容易出現循環引用問題導致內存不能被回收, 進行導致內存泄露等問題,一般不用引用計數法。




第二,標記清除法




到2008年爲止,IE,Firefox,Opera,Chrome和Safari的javascript實現使用的都是標記清除式的垃圾收集策略(或類似的策略),只不過垃圾收集的時間間隔互有不同。




標記清除的算法分爲兩個階段,標記(mark)和清除(sweep). 第一階段從引用根節點開始標記所有被引用的對象,第二階段遍歷整個堆,把未標記的對象清除。




(11)同源策略




同源策略是瀏覽器有一個很重要的概念。所謂同源是指,域名,協議,端口相同。不同源的客戶端腳本(javascript、ActionScript)在沒明確授權的情況下,不能讀寫對方的資源。簡單的來說,瀏覽器允許包含在頁面A的腳本訪問第二個頁面B的數據資源,這一切是建立在A和B頁面是同源的基礎上。




(12)跨域的幾種方式




jsonp(利用script標籤的跨域能力)跨域、websocket(html5的新特性,是一種新協議)跨域、設置代理服務器(由服務器替我們向不同源的服務器請求數據)、CORS(跨源資源共享,cross origin resource sharing)、iframe跨域、postMessage(包含iframe的頁面向iframe傳遞消息)




(13)異步和同步




同步指下一個程序的執行需要等到上一個程序執行完畢,也就是得出結果後下一個才能執行,




異步指的是上一個程序指向後,下一個程序不用等到上一個程序出結果就能執行,等上一個出結果了調用回調函數處理結果就好。




(14)JavaScript的值類型和引用類型




JavaScript有兩種類型的數據,值類型和引用類型,一般的數字,字符串,布爾值都是值類型,存放在棧中,而對象,函數,數組等是引用類型,存放在堆中,對引用類型的複製其實是引用複製,相當於複製着地址,對象並沒有真正的複製。




var a=5;var b=a;a=null;    //那麼b是5
var a={},var b=a;b.name="mbj";
console.log(a.name);   //mbj,因爲a,b指向同一個對象
a=null;console.log(typeof b);  //object,a=null,只是a不再指向該對象,但是這個對象還是在堆中確確實實的存在,b依然指向它。
(15)優化下面代碼




var str="我喜歡我可愛的女朋友,";
str=str+"她叫喵喵,";
str=str+"她時而可愛,時而認真,";
str=str+"她那天真的笑聲可以讓人忘掉一切煩惱。";
console.log(str);
這裏的優化主要是對加號操作符的優化,因爲加號在JavaScript中非常耗時和耗內存,需要經過以下六步:




1、首先開闢一塊臨時空間,存儲字符串,
2、然後在開闢一塊空間
3、把str中的字符串複製到剛剛開闢的空間
4、在把需要連接的字符串複製到str後面
5、str指向這塊空間
6、回收str原來的空間和臨時空間
優化的方法是使用數組的push方法,數組是連續的存儲空間,可以省下很多步




var res=[];
var str="我喜歡我可愛的女朋友,";
res.push(str);
res.push("她叫喵喵,");
res.push("她時而可愛,時而認真,");
res.push("她那天真的笑聲可以讓人忘掉一切煩惱。");
console.log(res.join(""));    
(16)封裝cookie的添加,刪除,查詢方法




cookie是存儲在瀏覽器端的,可以用於存儲sessionID,也可以用於自動登陸,記住密碼等,但是在瀏覽器端並沒有官方的操作cookie的方法,下面我們來封裝一下:




CookieUtil={
    addCookie:function(key,value,options){
        var str=key+"="+escape(value);
        if(options.expires){
           var curr=new Date();   //options.expires的單位是小時
           curr.setTime(curr.getTime()+options.expires*3600*1000);
           options.expires=curr.toGMTString();
        }
        for(var k in options){   //有可能指定了cookie的path,cookie的domain
           str+=";"+k+"="+options[k];
        }
        document.cookie=str;
    },
    queryCookie:function(key){
      var cookies=document.cookie;
     //獲得瀏覽器端存儲的cookie,格式是key=value;key=value;key=value
      cookies+=";";
      var start=cookies.indexOf(key);
      if(start<=-1){ return null; }  //說明不存在該cookie
      var end=cookies.indexOf(";",start);
      var value=cookies.slice(start+key.length+1,end);
      return unescape(value);
    },
    deleteCookie:function(key){
      var value=CookieUtil.queryCookie(key);
      if(value===null){return false;}
      CookieUtil.addCookie(key,value,{expires:0});//把過期時間設置爲0,瀏覽器會馬上自動幫我們刪除cookie
    }

(17)事件委託機制




事件委託指的是,不再事件的發生地設立監聽函數,而是在事件發生地的父元素或者祖先元素設置監聽器函數,這樣可以大大提高性能,因爲可以減少綁定事件的元素,比如:




<ul>
 <li></li>
 <li></li>
 <li></li>
</ul>
要給li元素綁定click事件,使用事件委託機制的話,就只需要給ul綁定click事件就行了,這樣就不需要給每個li'綁定click事件,減小內存佔用,提高效率,有興趣的童鞋可以去看看jQuery的live,bind,on,delegate函數的區別,這幾個函數就採用了事件委託機制。




三、其他部分




(1)http狀態碼




http狀態碼是表示服務器對請求的響應狀態,主要分爲以下幾個部分




1**:這類響應是臨時響應,只包含狀態行和某些可選的響應頭信息,並以空行結束




2**:表示請求成功,




3**:表示重定向




4**:表示客戶端錯誤




5**:表示服務器端錯誤




100(continue),客戶端應當繼續發送請求。這個臨時響應是用來通知客戶端它的部分請求已經被服務器接收




200(OK),表示請求成功,請求所希望的響應頭或數據體將隨此響應返回。




202(Accepted),服務器已接受請求,但尚未處理。




204(No-Content),服務器成功處理了請求,但不需要返回任何實體內容




205(Reset-Content),服務器成功處理了請求,且沒有返回任何內容。但是與204響應不同,返回此狀態碼的響應要求請求者重置文檔視圖。該響應主要是被用於接受用戶輸入後,立即重置表單,以便用戶能夠輕鬆地開始另一次輸入。




206(Partial-Content),服務器已經成功處理了部分 GET 請求。




301(Moved-Permanently),永久性重定向




302(Moved-Temporarily),暫時性重定向




304(Not-Modified),瀏覽器端緩存的資源依然有效




400(Bad-Reques),請求有誤,當前請求無法被服務器理解。




401(Unauthorized),當前請求需要用戶驗證。




403(Forbidden),服務器已經理解請求,但是拒絕執行它。




404(Not-Found),請求的資源沒有被找到




500(Interval Server Error),服務器內部錯誤




502(Bad GateWay),網關出錯




503(Service Unavailable),由於臨時的服務器維護或者過載,服務器當前無法處理請求。




504(Gateway Timeout),作爲網關或者代理工作的服務器嘗試執行請求時,未能及時從上游服務器(URI標識出的服務器,例如HTTP、FTP、LDAP)或者輔助服務器(例如DNS)收到響應。




(2)xss,csrf的概念以及防範方法




大公司如bat在面試的時候,web安全問題是必問的問題,所以一定要懂,要徹底理解xss和csrf的概念和防範方式,最好在項目中有用到對這兩種攻擊的防範,這樣會給你的面試加很多分。由xss和csrf涉及的東西比較多,我就不具體給出了,詳情請看XSS攻擊:http://blog.csdn.net/ghsau/article/details/17027893,CSRF攻擊:http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html




(3)CommonJs,AMD,CMD規範




對於前端模塊化來說,這三個規範是必須要了解的,詳情請看我的這篇文章https://zhuanlan.zhihu.com/p/22954387
(4)談談對前端模塊化的理解




前端模塊話就是把複雜的文件分成一個個獨立的模塊,比如js文件,分成獨立的模塊之後有利於代碼的重用和維護,但是這樣又會引來模塊與模塊之間的依賴問題,所以就有了CommonJS、AMD、CMD規範,最後出現了webpack,webpack就是前端模塊話的一種解決方案,基本上大公司都會使用webpack,想要詳細的學習webpack的話請看https://zhuanlan.zhihu.com/p/23538138




(5)優雅降級和漸進增強




優雅降級指的是一開始就構建功能完好的網站,然後在慢慢兼容低版本的瀏覽器,使得各個瀏覽器之間的差異不要太大。




漸進增強是指在基本功能得到滿足的情況下,對支持新特性的瀏覽器使用新特性,帶給用戶更換的體驗。




優雅降級和漸進增強的出發點不同,前者是慢慢向下兼容,是向後看,後着是慢慢向上,增強功能,是向前看。




(6)前端優化(提高網頁的加載速度)




1、使用css sprites,可以有效的減少http請求數




2、使用緩存




3、壓縮js,css文件,減小文件體積




4、使用cdn,減小服務器負擔




5、懶加載圖片




6、預加載css,js文件




7、避免dom結構的深層次嵌套




8、給DOM元素添加樣式時,把樣式放到類中,直接給元素添加類,減少重構,迴流




更多詳細的前端優化請看前端優化:http://www.tuicool.com/articles/J3uyaa




四、前端學習文章推薦




知乎上面有人推薦了很多前端學習網站,具體信息請看




https://www.zhihu.com/question/19651401/answer/46211739
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章