前端面試之旅:

如下問題基本針對於大廠一面和中等公司的一面二面,更多關於項目裏的問題還需根據自身參考。javascript

1、html

1.html5新增的特性?

語義標籤,加強型表單,視頻和音頻,Canvas繪圖,SVG繪圖,地理定位,拖放API,Web Worker。
css

2.BFC?

一塊獨立渲染區域。如下會造成BFC:html

  1. 根元素
  2. float屬性不爲none
  3. position爲absolute或fixed
  4. display爲inline-block, table-cell, table-caption, flex, inline-flex
  5. overflow不爲visible

做用:防止margin重疊,自適應兩欄佈局,清除內部浮動。前端

3.瀏覽器渲染過程?

  • 解析HTML生成DOM樹。
  • 解析CSS生成CSSOM規則樹。
  • 將DOM樹與CSSOM規則樹合併在一塊兒生成渲染樹。
  • 遍歷渲染樹開始佈局,計算每一個節點的位置大小信息。
  • 將渲染樹每一個節點繪製到屏幕。

2、css

1.css居中

水平居中:text-align:center,,flex,position:absolute+transformvue

垂直居中:line-height,flex,position:absolute+transform,table-cellhtml5

水平垂直居中:flex,position:absolute+transform.java

2.absolute和relative,fixed的區別

  • static 是默認值
  • relative 相對定位 相對於自身原有位置進行偏移,仍處於標準文檔流中
  • absolute 絕對定位 相對於最近的已定位的祖先元素, 有已定位(指position不是static的元素)祖先元素, 以最近的祖先元素爲參考標準。若是無已定位祖先元素, 以body元素爲偏移參照基準, 徹底脫離了標準文檔流。
  • fixed 固定定位的元素會相對於視窗來定位,這意味着即使頁面滾動,它仍是會停留在相同的位置。一個固定定位元素不會保留它本來在頁面應有的空隙。
  • 3.display:none和visibility:hidden區別

    display:none指的是元素徹底不陳列出來,不佔據空間,涉及到了DOM結構,故產生reflow與repaintnode

    visibility:hidden指的是元素不可見但存在,保留空間,不影響結構,故只產生repaint(脫離文檔流)webpack

    4.選擇器優先級,以及選擇器的疊加算法。

    !important>inline>ID>class>taggit

    • 第一等級:表明內聯樣式,如style="",權值爲 1000
    • 第二等級:表明id選擇器,如#content,權值爲100
    • 第三等級:表明類,僞類和屬性選擇器,如.content,權值爲10
    • 第四等級:表明標籤選擇器和僞元素選擇器,如div p,權值爲1

    3、javascript基礎

    1.深拷貝與淺拷貝

    這個問題呢,基本上是必問的。因此這一題,咱們從js的變量提及,從內存空間提及:

    其中,JavaScript中變量類型有兩種:

    1. 基礎類型(Undefined, Null, Boolean, Number, String, Symbol)一共6種
    2. 引用類型(Object)

    基礎類型的值保存在棧中,這些類型的值有固定大小,"按值來訪問"

    引用類型的值保存在堆中,棧中存儲的是引用類型的引用地址(地址指針),"按引用訪問",引用類型的值沒有固定大小,可擴展(一個對象咱們能夠添加多個屬性)。

    所以進行拷貝的時候便分爲兩種拷貝:

    • "淺拷貝:棧存儲拷貝
    • "深拷貝:堆存儲拷貝

    深拷貝的幾種實現方法

    2.對執行上下文的理解

    關於js執行上下文:

    執行上下文(Execution Context): 函數執行前進行的準備工做(也稱執行上下文環境)

    js中執行上下環境(上下文):

    • 全局執行上下環境
    • 函數執行上下環境
    • eval函數環境

    由於js是單線程,所以,js代碼執行就相似於出棧,入棧過程。js中,全局永遠在棧底,代碼示例:

    function foo () {
        function bar () {
            return 'I am bar';
        }
        return bar();
    }
    foo();複製代碼


    從這裏能夠看出執行上下文的生命週期:

    1. 建立階段(進入執行上下文)
    2. 執行階段(代碼執行

    關於上下文不一樣階段的做用可參考這篇文章

    3.什麼是原型鏈?什麼是做用域?什麼是閉包?js繼承的幾種方式?

    什麼是原型

       每一個函數默認都有一個 prototype 屬性,它就是咱們所說的 "原型",或稱 "原型對象"。每一個實例化建立的對象都有一個 __proto__ 屬性(隱式原型),它指向建立它的構造函數的 prototype 屬性。

    什麼是原型鏈:(基本是基於構造函數)

      訪問一個對象的屬性時,會先在其基礎屬性上查找,找到則返回值;若是沒有,會沿着其原型鏈上進行查找,整條原型鏈查找不到則返回 undefined。這就是原型鏈查找。

    function a(){};
    a.prototype.name = "追夢子";
    var b = new a();
    console.log(b.name); //追夢子複製代碼
    所以從原型咱們能夠談到繼承:

    1.原型繼承

    // 建立父類一個類
    function Father(name){
    	//屬性
    	this.name = name || 'father'
            // 實例方法
    	this.run = function(){
    		 console.log(this.name + '正在跑步!');
    	}
    }
    //原型上的方法
    Father.prototype.sayName = function() {
        console.log(this.name+'正在跑步');
    }
    //原型鏈繼承
    function Son(){
        this.subName = '兒子'
    }
    // 建立Son的實例,並將原型指向Father
    Son.prototype = new Father()
    Son.prototype.saySubName = function() {
        console.log(this.subName+'正在跑步');
    }
    var son = new Son()
    console.log(son.sayName()) // father正在跑步
    console.log(son) //能夠看看son的原型指向複製代碼


    // 建立父類一個類
    function Father(name){
        //屬性
        this.color = ['r','e']
    }
    //原型鏈繼承
    function Son(){}
    Son.prototype = new Father()
    var sonOne = new Son()
    sonOne.color.push('d')
    console.log(sonOne.color)//["r", "e", "d"]
    var sonTwo = new Son()
    console.log(sonTwo.color)//["r", "e", "d"]
    特色:基於原型鏈,既是父類的實例,也是子類的實例
    缺點:對於上 引用型值的繼承容易形成全部實例共享複製代碼

    2.構造函數繼承

    // 建立父類一個類
    function Father(name){
        //屬性
        this.color = name || ['r','e']
    }
    //原型上的方法
    Father.prototype.sayColors = function() {
        console.log(this.color);
    
    }//構造函數繼承
    function Son(){
        Father.call(this) //只有函數纔會有call,apply,bind
    }
    // 實例1
    var sonOne = new Son()
    // 實例二
    var sonTwo = new Son()
    sonOne.color.push('d')
    console.log(sonOne.color)//["r", "e", "d"]
    console.log(sonTwo.color)// ["r", "e"]
    console.log(sonTwo)
    console.log(sonTwo instanceof Son) // true
    console.log(sonTwo instanceof Father) //false
    console.log('是否繼承了原型上方法', sonTwo.sayColors()) // error
    特色: 能夠實現多繼承
    缺點:只能繼承父類實例的屬性和方法,不能繼承原型上的屬性和方法,而且複用性太弱。複製代碼


    3.組合式繼承:(原型繼承+構造繼承)

    function Father(colors){
          //屬性
          this.color = colors || ['r','e']
      }
      //原型上的方法
      Father.prototype.sayColors = function() {
          console.log(this.color);
      }
      //構造函數繼承
      function Son(name, color){
          Father.call(this, color) //第二次調用Father()
          this.name = name
    	  this.sayName = function(){
    			console.log(this.name)	
    	   }
      }
      Son.prototype = new Father() //第一次調用Father()
      var sonOne = new Son('兒子1', ['r','e', 'd'])
      sonOne.sayColors() //["r", "e", "d"] 
      sonOne.sayName() //兒子1
      var sonTwo = new Son('兒子2', ['g','r', 'e'])
      sonTwo.sayColors() //["g", "r", "e"]
      sonTwo.sayName() //兒子2
      console.log(sonTwo) //如下圖片是sonTwo
      特色:既繼承了實例的屬性和方法,也繼承了原型上的屬性和方法
      缺點:調用了兩次父類構造函數,生成了兩份實例
    複製代碼


    4.寄生式組合繼承(不進行兩次調用,直接將父類原型複製給子類原型)

    function Father(colors){
          //屬性
          this.color = colors || ['r','e']
      }
      //原型上的方法
      Father.prototype.sayColors = function() {
          console.log(this.color);
      }
      //構造函數繼承
      function Son(name, colors){
          Father.call(this, colors)
          this.name = name
    	  this.sayName = function(){
    			console.log(this.name)	
    	   }
      }
      function jisheng(subPro,superPro){
        let pro = Object(superPro)    
        pro.constructor = subPro    
        subPro.prototype = pro  }
      jisheng(Son,Father)
      var sonOne = new Son('兒子1', ['r','e', 'd'])
      sonOne.sayColors() //  ['r','e', 'd']
      sonOne.sayName() // 兒子1
      var sonTwo = new Son('兒子2', ['g','r', 'e'])
      sonTwo.sayColors() // ['g','r', 'e']
      sonTwo.sayName() // 兒子2
      console.log(sonTwo) //如下是sonTwo的截圖複製代碼


    什麼是做用域:(針對變量)

      至關於針對這些變量的訪問權限的合集。(至關於一個省(全局做用域)下的各類市,縣。。。都有不一樣的地盤)

    var globaValue = '我是省做用域';
    function chengdu() {
        var fooValue = '我是chengdu做用域';    function wuhou() {
            var barValue = '我是wuhou做用域';    }
    }
    
    function mianyang() {
        var otherValue = '我是mianyang做用域';
    }複製代碼

    什麼是做用域鏈:和原型鏈同樣,是一個查找過程

    var a = 1;
    var b = 2;
    function b(){
        var a = 2;
        function c(){
            var a = 3;
            console.log(a);
           console.log(b);
    }    c();
    }
    b();//3 2
    當在c的做用域中找到a,就中止查找,打印a,繼續向上找b,b函數的做用域中沒有b,
    則繼續沿着做用域鏈往上找,在全局中找到b。複製代碼

    所以從做用域咱們能夠談到閉包:閉包就是指有權訪問另外一個函數做用域中的變量的函數。

    // 如下就是閉包的應用
    function test(){
      var arr = [];
      for(var i = 0;i < 10;i++){ //i是在test做用域裏
        arr[i] = function(){ //函數二做用域
          return i;
        };
      }
      for(var a = 0;a < 10;a++){
        console.log(arr[a]());
      }
    }
    test(); //打印10個10,由於i在test執行的時候最後 for循環遍歷i變爲10,所以在函數二的做用域中沒有i,
    就向上找。
    
    
    //變量被保存在了內存中function test(){ 
      var a = 1
      return function(){
    	a++
    	console.log(a)
      }
    }
    var func = test()
    func() // 2
    func() // 3
    
    //閉包中的this指向
    var name = "The Window";
    var obj = {
      name: "My Object",
      
      getName: function(){
        return function(){
          return this.name;
        };
      }
    };
    
    console.log(obj.getName()()); // 其實是在全局做用域中調用了匿名函數,this指向了window。
      //這裏要理解函數名與函數功能(或者稱函數值)是分割開的,不要認爲函數在哪裏,
      //其內部的this就指向哪裏。匿名函數的執行環境具備全局性,所以其 this 對象一般指向 window。複製代碼

    4.new作了什麼?

     1. 建立一個新的對象,this變量引用該對象,同時還繼承了該函數的原型

     2. 屬性和方法都被添加到this 引用的對象中去

     3. 新建立的對象由this所引用,而且最後隱式的返回this

    5.promise是什麼,手寫一個promise?

    promise解決異步的三種狀態

    • pending
    • fulfilled
    • rejected

    (1) promise 對象初始化狀態爲 pending

    (2) 當調用resolve(成功),會由pending => fulfilled

    (3) 當調用reject(失敗),會由pending => rejected

    注意promsie狀態 只能由 pending => fulfilled/rejected, 一旦修改就不能再變

    6.setTimeOut和promise的區別?

    在說區別以前,咱們先看一個例子

    var p1 = new Promise(function(resolve, reject){
        resolve(1);
    })
    setTimeout(function(){
      console.log("will be executed at the top of the next Event Loop");
    },0)
    p1.then(function(value){
      console.log("p1 fulfilled");
    })
    setTimeout(function(){
      console.log("will be executed at the bottom of the next Event Loop");
    },0)
    
    p1 fulfilled
    will be executed at the top of the next Event Loop
    will be executed at the bottom of the next Event Loop複製代碼

    由於javascriot是單線程,在其JavaScript事件循環併發模型中,

    咱們瞭解setTimeout和Promise調用的都是異步任務,這一點是它們共同之處,也即都是經過任務隊列進行管理/調度

    JavaScript經過任務隊列管理全部異步任務,而任務隊列還能夠細分爲MacroTask Queue(宏任務)和MicoTask Queue(微任務)兩類。


    MacroTask Queue(宏任務隊列)主要包括setTimeout,setInterval, setImmediate, requestAnimationFrame, NodeJS中的`I/O等。

    MicroTask Queue(微任務隊列)主要包括兩類:
    獨立回調microTask:如Promise,其成功/失敗回調函數相互獨立;
    複合回調microTask:如 Object.observe, MutationObserverNodeJs中的 process.nextTick ,不一樣狀態回調在同一函數體;

    總的來講就是若是代碼按順序執行,就是一個進入是最大的宏任務,先執行第一個宏任務而後執行宏任務裏的微任務,在執行下一個宏任務。

    4、網絡和安全

    1.post和get的區別?

  • GET在瀏覽器回退時是無害的,而POST會再次提交請求。
  • GET產生的URL地址能夠被Bookmark,而POST不能夠。
  • GET請求會被瀏覽器主動cache,而POST不會,除非手動設置
  • GET請求的參數會完整的被保存在歷史記錄裏,POST不會。
  • GET請求參數放在URL中,POST放在request body中。
  • GET請求只能進行url編碼,POST請求支持多種編碼方式。
  • 對於參數類型,GET只接受ASCII字符,而POST沒有限制。
  • GET請求在URL中傳遞的參數是有長度限制的(理論上就是url的長度),而POST沒有。
  • 都是Tcp鏈接,最大的區別就是:

    GET產生一個TCP數據包;POST產生兩個TCP數據包。

    2.瀏覽器的緩存機制?

    對於一個數據請求來講,能夠分爲發起網絡請求、後端處理、瀏覽器響應三個步驟。而瀏覽器則能幫助咱們在第一步和第三步優化性能,減小數據請求。

    其中,緩存位置分爲四種:

    • Service Worker(運行在瀏覽器背後的獨立線程,必須使用https保障安全)

    • Memory Cache(內存中的緩存,讀取速度快,緩存持續性很短)

    • Disk Cache(存儲在硬盤中的緩存,讀取速度慢)

    • Push Cache(推送緩存,以上三種緩存都沒有命中時,它纔會被使用,會話中存在)

    關於瀏覽器緩存能夠參照「深刻理解瀏覽器緩存機制」,如下是瀏覽器緩存過程分析(圖來自網絡):

    是否須要向服務器從新發起HTTP請求將緩存過程分爲兩個部分:

    • 強制緩存(不會向服務器發送請求,從緩存中讀取)
    • 協商緩存(強制緩存失效,瀏覽器從新攜帶緩存標識發起請求,從而讓服務器決定是否啓用緩存的過程)

    第一次发起HTTP请求


    前端清理緩存的幾種方法:

    //不緩存meta標籤
    <META HTTP-EQUIV="pragma" CONTENT="no-cache"> 
    <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate"> 
    <META HTTP-EQUIV="expires" CONTENT="0">
    
    //form表單
    <body onLoad="javascript:document.yourFormName.reset()">
    //ajax請求時
    cache:false || 
    beforeSend :function(xmlHttp){ 
      xmlHttp.setRequestHeader("If-Modified-Since","0");
      xmlHttp.setRequestHeader("Cache-Control","no-cache");
    },
    
    //url參數上加隨機數或者隨機時間
    
    複製代碼

    3.cookie和session的區別以及機制?

    爲何須要cookie和session?

    http是無狀態的,服務端不能跟蹤客戶端的狀態。

        cookie機制:

             若是不在瀏覽器中設置過時時間,cookie被保存在內存中,生命週期隨瀏覽器的關閉而結束,這種cookie簡稱會話cookie。若是在瀏覽器中設置了cookie的過時時間,cookie被保存在硬盤中,關閉瀏覽器後,cookie數據仍然存在,直到過時時間結束才消失。

    Cookie是服務器發給客戶端的特殊信息,cookie是以文本的方式保存在客戶端,每次請求時都帶上它

         session機制:

             當服務器收到請求須要建立session對象時,首先會檢查客戶端請求中是否包含sessionid。若是有sessionid,服務器將根據該id返回對應session對象。若是客戶端請求中沒有sessionid,服務器會建立新的session對象,並把sessionid在本次響應中返回給客戶端。一般使用cookie方式存儲sessionid到客戶端,在交互中瀏覽器按照規則將sessionid發送給服務器。若是用戶禁用cookie,則要使用URL重寫,能夠經過response.encodeURL(url) 進行實現;API對encodeURL的結束爲,當瀏覽器支持Cookie時,url不作任何處理;當瀏覽器不支持Cookie的時候,將會重寫URL將SessionID拼接到訪問地址後。

    4.cookie,localstorage和sessionstorage的區別?

    cookie:大小限制4KB,會浪費一部分發送cookie時使用的帶寬,要正確的操縱cookie是很困難的。

    webStorage包括如下兩種:數據存儲大小是5MB,字符串類型

    localstorage:永久保存,除非手動清除clear()。

    sessionstorage:臨時保存,關閉了瀏覽器窗口後就會被銷燬

    5.XSS(跨站腳本)攻擊以及如何防範?

    原理: 惡意攻擊者往Web頁面裏插入惡意html代碼,當用戶瀏覽該頁之時,嵌入其中Web裏面的 (html代碼/javascript代碼) 會被執行,從而達到惡意攻擊用戶的特殊目的。

    • 反射型 XSS:是指發生請求時,XSS代碼出如今請求URL中,做爲參數提交到服務器,服務器解析並響應。響應結果中包含XSS代碼,最後瀏覽器解析並執行。
    • 存儲型 XSS:將XSS代碼發送到服務器(無論是數據庫、內存仍是文件系統等。),而後在下次請求頁面的時候就不用帶上XSS代碼了。
    • DOM XSS:不一樣於反射型XSS和存儲型XSS,DOM XSS代碼不須要服務器端的解析響應的直接參與,而是經過瀏覽器端的DOM解析。這徹底是客戶端的事情。

    解決方法:過濾危險節點,cookie設置成httponly

    6.CSRF(跨站點請求僞造)攻擊以及如何防範?

    原理:CSRF攻擊者在用戶已經登陸目標網站以後,誘使用戶訪問一個攻擊頁面,利用目標網站對用戶的信任,以用戶身份在攻擊頁面對目標網站發起僞造用戶操做的請求,達到攻擊目的。

    解決方法:儘可能使用POST,限制GET;瀏覽器Cookie策略;加驗證碼;Referer Check;Anti CSRF Token服務端加token,在提交請求時附上,看是否與服務端一致。

    7.性能優化

  • 減小 HTTP 請求數
  • 減小 DNS 查詢
  • 使用 CDN
  • 避免重定向
  • 圖片懶加載
  • 減小 DOM 元素數量
  • 減小 DOM 操做
  • 使用外部 JavaScriptCSS
  • 壓縮 JavaScriptCSS 、字體、圖片等
  • 優化 CSS Sprite
  • 使用 iconfont
  • 字體裁剪
  • 多域名分發劃份內容到不一樣域名
  • 儘可能減小 iframe 使用
  • 避免圖片 src 爲空
  • 把樣式表放在 中
  • 把腳本放在頁面底部
  • 5、框架

    1.vue的雙向綁定原理?

    Object.defineProperty複製代碼

    2.vue-router採用的原理?以及query和param傳參的差異?

    1. hash ---- 利用URL中的hash(「#」):HashHistory.push(),HashHistory.replace()

    2. 利用History interface在 HTML5中新增的方法:pushState(), replaceState()

      • pushState設置的新URL能夠是與當前URL同源的任意URL;而hash只可修改#後面的部分,故只可設置與當前同文檔的URL

      • pushState設置的新URL能夠與當前URL如出一轍,這樣也會把記錄添加到棧中;而hash設置的新值必須與原來不同纔會觸發記錄添加到棧中

      • pushState經過stateObject能夠添加任意類型的數據到記錄中;而hash只可添加短字符串

      • pushState可額外設置title屬性供後續使用

    3.vuex的原理以及適用場景?

    4.v-if和v-show的區別?談到重排和重繪

    v-if: 移除在dom中的顯示,將dom元素移除
    v-show: dom元素還在,至關於display:none
    display:none --元素被隱藏, 和 visibility: hidden
    重排和重繪:重排包括重繪,重繪不必定包括重排
    引發重排:
    (1)頁面渲染初始化時;(這個沒法避免)
    (2)瀏覽器窗口改變尺寸;
    (3)元素尺寸改變時;
    (4)元素位置改變時;
    (5)元素內容改變時;
    (6)添加或刪除可見的DOM 元素時。

    5.vue的生命週期?

    • beforeCreate
    • created
    • beforeMount
    • mounted
    • beforeUpdate
    • updated
    • beforeDestroy
    • destroyed

    6.angular的雙向綁定原理?

    7.rxjs對可觀察對象的理解?

    6、node.js

    1.express寫中間件

    7、數據結構與算法

    1.對比棧,隊列,數組,鏈表這些結構的優缺點?2.排序算法?3.廣度優先遍歷深度優先遍歷算法?

    8、git

    1.git fecth和git pull的區別?

       git pull至關於git fecth + git merge。git fecth只能改變遠程倉庫裏的代碼,本地head不能改變。

    9、webpack

    1.sourcemap有多少種?

    爲何須要source-map,爲了解決代碼通過編譯打包出錯以後定位問題。

    webpack官網一共有11種,無非就是包括:打包後(none),生成後的代碼,轉換後的代碼(僅限行:每行一個映射),原始源代碼(僅限行),原始源代碼,無源代碼內容。對於開發環境,一般但願更快速的 source map,須要添加到 bundle 中以增長體積爲代價,可是對於生產環境,則但願更精準的 source map,須要從 bundle 中分離並獨立存在。

    如下是開發環境經常使用推薦的:

    配置:devtool: 'cheap-eval-source-map'




    生產環境是最好不要看到源碼,推薦devtool:none

    2.如何實現vue-cli中打出不一樣的好比vendor.js,app.js....?

    3.打包優化?

    相關文章
    相關標籤/搜索