<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          新出爐大廠面試題100道整理(原題 + 精講 1.2萬字)(一)

          共 20233字,需瀏覽 41分鐘

           ·

          2021-01-15 21:45


          大家喜歡的可以給筆者點個贊,花費了很長時間整理,這些面試題更適合中級前端,和需要進(jìn)階的高級前端的小伙伴,查缺補漏,為金九銀十保駕護(hù)航??????

          html篇


          . 問題一:Meta標(biāo)簽常用屬性值的寫法和作用

          答:
          meta 標(biāo)簽提供關(guān)于HTML文檔的元數(shù)據(jù)。元數(shù)據(jù)不會顯示在頁面上,但是對于機(jī)器是可讀的。它可用于瀏覽器(如何顯示內(nèi)容或重新加載頁面),搜索引擎(關(guān)鍵詞),或其他 web 服務(wù)。

          必要屬性

          name:屬性名
          content:屬性內(nèi)容
          charset: charset為HTML5中新增的,用來聲明字符編碼;
          http-equiv:屬性在HTML4中有很多值,在HTML5中只有refresh、default-style、content-type可用

          name的值和說明

          application name ? ?當(dāng)前頁所屬Web應(yīng)用系統(tǒng)的名稱
          keywords ? ? ? ? ? ?描述網(wǎng)站內(nèi)容的關(guān)鍵詞,以逗號隔開,用于SEO搜索
          description ? ? ? ? ? ?當(dāng)前頁的說明
          author ? ? ? ? ? ? ? ?當(dāng)前頁的作者名
          copyright ? ? ? ? ? ?版權(quán)信息
          renderer ? ? ? ? ? ?renderer是為雙核瀏覽器準(zhǔn)備的,用于指定雙核瀏覽器默認(rèn)以何種方式渲染頁面
          viewreport ? ? ? ? ? ?它提供有關(guān)視口初始大小的提示,僅供移動設(shè)備使用

          viewreport
          meta標(biāo)簽的name屬性值為viewreport時的視口的大小

          1.content內(nèi)容為空時,默認(rèn)視口寬度為980
          2.content設(shè)置width,不設(shè)置initail-scale時,視口寬度為設(shè)置的width值
          3.content不設(shè)置width,只設(shè)置initail-scale時,是可以根據(jù)initail-scale的值計算出視口的寬度
          initail-scale = 屏幕寬度 / 視口寬度
          4.content同時設(shè)置width和initail-scale時,視口寬度為width的值,頁面顯示按照initail-scale比率進(jìn)行縮放
          5.一般都是進(jìn)行如下設(shè)置,來實現(xiàn)視口寬等于設(shè)備寬,布局完成后屏幕顯示也不進(jìn)行縮放

          <meta?name="viewport"?content="width=device-width,?initial-scale=1.0">

          聲明字符編碼
          charset屬性為HTML5新增的屬性,用于聲明字符編碼,以下兩種寫法效果一樣

          <meta?charset="utf-8">?//HTML5

          模擬http標(biāo)頭字段

          http-equiv屬性與content屬性結(jié)合使用, http-equiv屬性為指定所要模擬的標(biāo)頭字段的名稱,content屬性用來提供值。

          <meta?http-equiv="參數(shù)"?content="具體的描述">

          content-Type 聲明網(wǎng)頁字符編碼:

          <meta?http-equiv="content-Type"?content="text/html?charset=UTF-8">

          refresh 指定一個時間間隔(以秒為單位),在此時間過去之后從服務(wù)器重新載入當(dāng)前頁面,也可以另外指定一個頁面.

          <meta?http-equiv="refresh"?content="2;URL=http://www.baidu.com">//2秒后在當(dāng)前頁跳轉(zhuǎn)到百度

          X-UA-Compatible 瀏覽器采取何種版本渲染當(dāng)前頁面

          <meta?http-equiv="X-UA-Compatible"?content="IE=edge,chrome=1">?//指定IE和Chrome使用最新版本渲染當(dāng)前頁面

          expires 用于設(shè)定網(wǎng)頁的到期時間,過期后網(wǎng)頁必須到服務(wù)器上重新傳輸

          <meta?http-equiv="expires"?content="Sunday?22?July?2016?16:30?GMT">

          catch-control 用于指定所有緩存機(jī)制在整個請求/響應(yīng)鏈中必須服從的指令

          <meta?http-equiv="cache-control"?content="no-cache">

          js篇


          . 問題1: 給對象加上iterator接口,使之能被 for of遍歷

          ES6 規(guī)定,默認(rèn)的 Iterator 接口部署在數(shù)據(jù)結(jié)構(gòu)的 Symbol.iterator 屬性,或者說,一個數(shù)據(jù)結(jié)構(gòu)只要具有Symbol.iterator屬性,就可以認(rèn)為是“可遍歷的”(iterable)。Symbol.iterator 屬性本身是一個函數(shù),就是當(dāng)前數(shù)據(jù)結(jié)構(gòu)默認(rèn)的遍歷器生成函數(shù)

          因為object 沒有 Symbol.iterator 屬性,所以不能被 for of 遍歷。

          const?text?=?{
          ???a:?1,
          ???b:?2,
          ???c:3
          }
          for(let?i?of?text){
          ????console.log(i)?//報錯:Uncaught TypeError: text is not iterable
          }

          所以,object想要被 for … of遍歷 ,必須在原來的基礎(chǔ)上加上 Symbol.iterator 接口屬性。

          const?text?=?{
          ???a:?1,
          ???b:?2,
          ???c:3
          }
          text[Symbol.iterator]?=?function?(){
          ????const?_this?=?this
          ????return?{
          ????????index:-1,
          ????????next(){
          ????????????const?arr?=?Object.keys(?_this?)
          ????????????if(this.index?????????????????this.index++
          ????????????????return?{
          ????????????????????value:_this[arr[this.index]],
          ????????????????????done:false
          ????????????????}
          ????????????}else{
          ????????????????return?{
          ????????????????????value:undefined,
          ????????????????????done:true
          ????????????????}
          ????????????}
          ????????}
          ????}
          }

          for(let?i?of?text){
          ????console.log(i)?//?1?2?3?undefined
          }

          . 問題2:統(tǒng)計按鈕一秒鐘點擊次數(shù)?

          這道題是變相考對防抖函數(shù)+閉包的理解

          <script>

          const?button?=?document.getElementById('button')
          function?debounce(fn,?time)?{
          ????let?number?=?0?,?timer??=?null
          ????return?function(...arg)?{?
          ????????fn.apply(this,?arg)
          ????????number++
          ????????if?(timer)?return
          ????????timer?=?setTimeout(()?=>?{
          ???????????console.log(?'點擊'+?number?+?'次'?)
          ???????????number?=?0
          ???????????timer?=?null
          ????????},?time)
          ????}
          }
          button.onclick?=?debounce(()=>{
          ????console.log(1111)
          },1000)

          script>

          效果如下

          . 問題3:單頁面應(yīng)用路由的原理

          無論我們用vue還是react構(gòu)建單頁面應(yīng)用,都離不開路由的概念,路由跳轉(zhuǎn)監(jiān)聽url改變,根據(jù)路由的改變來決定渲染的頁面。

          hash模式

          改變路由

          const?path?=?"home"
          window.location.hash?=?path

          監(jiān)聽路由

          window.addEventListener('hashchange',function(e){
          ??//路由發(fā)生改變時切換渲染組件...
          });

          histroy模式

          改變路由

          var?path?=?"home"
          history.pushState(null,null,'?='+path);

          監(jiān)聽路由

          window.addEventListener('popstate',function(e){
          ???//路由發(fā)生改變時切換渲染組件...
          })

          . 問題4:如下打印結(jié)果

          執(zhí)行如下代碼,回發(fā)生什么?

          function?fn1(){
          ????console.log(a)
          }
          var?a?=?1

          function?fn2(){
          ????console.log(a)
          ????let?a?=?2;
          ????console.log(a)
          ????fn1()
          }

          fn2()

          結(jié)果://Uncaught ReferenceError: Cannot access 'a' before initialization

          let 暫時性死區(qū)

          let/const是使用區(qū)塊作用域;var是使用函數(shù)作用域

          在let/const聲明之前就訪問對應(yīng)的變量與常量,會拋出ReferenceError錯誤;但在var聲明之前就訪問對應(yīng)的變量,則會得到undefined

          console.log(a)?//?undefined
          console.log(b)?//?causes?ReferenceError:?b?is?not?defined
          var?a?=?1
          let?b?=?2?

          . 問題5:apply和call,bind的區(qū)別

          apply,call和bind都是 用來改變this的指向

          apply和call會讓當(dāng)前函數(shù)立即執(zhí)行,而bind會返回一個函數(shù),后續(xù)需要的時候再調(diào)用執(zhí)行

          apply,call的區(qū)別實參數(shù)不同

          const?foot?={
          ????apple:'蘋果'
          }
          function?eat(a,b){
          ???console.log(a,b,this)
          }

          const?bindEat?=?eat.bind(foot)

          eat(1,2)?//?1?2?Window

          bindEat(1,2)?//1?2??foot?

          eat.call(foot,1,2)?//1?2??foot

          /*?apply參數(shù)已數(shù)組形式傳遞??*/
          eat.apply(foot,[1,2])?//1?2??foot

          . 問題6:開發(fā)過程中遇到的內(nèi)存泄露情況,如何解決的?

          javascript內(nèi)存泄漏幾種情況

          1 意外的全局變量

          function?foo(arg)?{?
          ????bar?=?"this?is?a?hidden?global?variable";?
          }

          另一種意外的全局變量可能由 this 創(chuàng)建:

          function?foo()?{?
          ????this.variable?=?"potential?accidental?global";?
          }?
          //?Foo?調(diào)用自己,this?指向了全局對象(window)?
          //?而不是?undefined?
          foo();

          盡管我們討論了一些意外的全局變量,但是仍有一些明確的全局變量產(chǎn)生的垃圾。它們被定義為不可回收(除非定義為空或重新分配)。尤其當(dāng)全局變量用于 臨時存儲和處理大量信息時,需要多加小心。如果必須使用全局變量存儲大量數(shù)據(jù)時,確保用完以后把它設(shè)置為 null 或者重新定義。與全局變量相關(guān)的增加內(nèi)存消耗的一個主因是緩存。緩存數(shù)據(jù)是為了重用,緩存必須有一個大小上限才有用。高內(nèi)存消耗導(dǎo)致緩存突破上限,因為緩 存內(nèi)容無法被回收。

          2被遺忘的計時器或回調(diào)函數(shù)

          var?someResource?=?getData();?
          setInterval(function()?{?
          ????var?node?=?document.getElementById('Node');?
          ????if(node)?{?
          ????????//?處理?node?和?someResource?
          ????????node.innerHTML?=?JSON.stringify(someResource));?
          ????}?
          },?1000);

          與節(jié)點或數(shù)據(jù)關(guān)聯(lián)的計時器不再需要,node 對象可以刪除,整個回調(diào)函數(shù)也不需要了??墒牵嫊r器回調(diào)函數(shù)仍然沒被回收(計時器停止才會被回收)。同時,someResource 如果存儲了大量的數(shù)據(jù),也是無法被回收的。

          3脫離 DOM 的引用

          var?elements?=?{?
          ????button:?document.getElementById('button'),?
          ????image:?document.getElementById('image'),?
          ????text:?document.getElementById('text')?
          };?

          function?doStuff()?{?
          ????image.src?=?'http://some.url/image';?
          ????button.click();?
          ????console.log(text.innerHTML);?
          ????//?更多邏輯?
          }?

          function?removeButton()?{?
          ????//?按鈕是?body?的后代元素?
          ????document.body.removeChild(document.getElementById('button'));?

          ????//?此時,仍舊存在一個全局的?#button?的引用?
          ????// elements 字典。button 元素仍舊在內(nèi)存中,不能被 GC 回收。?
          }

          4 閉包的錯誤使用

          var?theThing?=?null;?
          var?replaceThing?=?function?()?{?
          ??var?originalThing?=?theThing;?
          ??var?unused?=?function?()?{?
          ????if?(originalThing)?
          ??????console.log("hi");?
          ??};?
          ??theThing?=?{?
          ????longStr:?new?Array(1000000).join('*'),?
          ????someMethod:?function?()?{?
          ??????console.log(someMessage);?
          ????}?
          ??};?
          };?
          setInterval(replaceThing,?1000);?

          每次調(diào)用 replaceThing ,theThing 得到一個包含一個大數(shù)組和一個新閉包(someMethod)的新對象。同時,變量 unused 是一個引用 originalThing 的閉包(先前的 replaceThing 又調(diào)用了 theThing )。思緒混亂了嗎?最重要的事情是,閉包的作用域一旦創(chuàng)建,它們有同樣的父級作用域,作用域是共享的。someMethod 可以通過 theThing 使用,someMethod 與 unused 分享閉包作用域,盡管 unused從未使用,它引用的 originalThing 迫使它保留在內(nèi)存中(防止被回收)。當(dāng)這段代碼反復(fù)運行,就會看到內(nèi)存占用不斷上升,垃圾回收器(GC)并無法降低內(nèi)存占用。本質(zhì)上,閉包的鏈表已經(jīng)創(chuàng)建,每一個閉包作用域攜帶一個指向大數(shù)組的間接的引用,造成嚴(yán)重的內(nèi)存泄露。

          解決內(nèi)存泄漏方式

          1 使用嚴(yán)格模式,合理聲明變量。使用嚴(yán)格模式可以避免第一種情況的發(fā)生。

          2 及時清理定時器,延時器,對于不需要的定時器和延時器,一定要及時清除。

          3 合理應(yīng)用閉包,合理的應(yīng)用閉包,避免閉包函數(shù)反復(fù)執(zhí)行導(dǎo)致內(nèi)存無法及時釋放。

          . 問題7:介紹一下proto和prototype

          proto和prototype 是我們在平時工作中容易忽略的問題,對象原型 和 原型鏈 的概念也容易混淆。

          proto是每個對象都有的屬性 ,在JS里,萬物皆對象。方法(Function)是對象,方法的原型(Function.prototype)是對象。因此,它們都會具有對象共有的特點。即:對象具有屬性proto,可稱為隱式原型,一個對象的隱式原型指向構(gòu)造該對象的構(gòu)造函數(shù)的原型,這也保證了實例能夠訪問在構(gòu)造函數(shù)原型中定義的屬性和方法。

          prototypee是函數(shù)才有的屬性,方法(Function)方法這個特殊的對象,除了和其他對象一樣有上述proto屬性之外,還有自己特有的屬性——原型屬性(prototype),這個屬性是一個指針,指向一個對象,這個對象的用途就是包含所有實例共享的屬性和方法就是該實例的proto。原型對象也有一個屬性,叫做constructor,這個屬性包含了一個指針,指回原構(gòu)造函數(shù)。

          ?let?a?=?function?(){

          ?}
          ?a.prototype.eat?=?function(){?console.log(111)?}
          ?const?na?=?new?a()
          ?console.log(?na.__proto__?===?a.prototype?)?//?ture

          . 問題8:說一下arguments對象

          在函數(shù)調(diào)用的時候,瀏覽器每次都會傳遞進(jìn)arguments對象,arguments 對象實際上是所在函數(shù)的一個內(nèi)置類數(shù)組對象,arguments對象不是一個 Array 。它類似于Array,但除了length屬性和索引元素之外沒有任何Array屬性。例如,它沒有 pop 方法。但是它可以被轉(zhuǎn)換為一個真正的Array.typeof參數(shù)返回 'object'。

          屬性
          arguments.callee指向參數(shù)所屬的當(dāng)前執(zhí)行的函數(shù)。指向調(diào)用當(dāng)前函數(shù)的函數(shù)。
          arguments.length傳遞給函數(shù)的參數(shù)數(shù)量。
          arguments[@@iterator]返回一個新的Array 迭代器 對象,該對象包含參數(shù)中每個索引的值。

          . 問題9:怎么實現(xiàn)一個隊列的數(shù)據(jù)結(jié)構(gòu)?

          介紹
          隊列也是一種線性表。它允許在表的一端插入數(shù)據(jù),在另一端刪除元素。插入元素的這一端稱之為隊尾。刪除元素的這一端我們稱之為隊首。

          特性
          1 在隊尾插入元素,在隊首刪除元素。
          2 FIFO(先進(jìn)先出),就向排隊取票一樣。

          簡單js實現(xiàn)

          class?Queue?{
          ????constructor(){
          ????????this.queue?=?[]
          ????}
          ????/*?進(jìn)入隊列?*/
          ????enqueue(item){
          ????????this.queue.push(item)
          ????}
          ????/*?移除隊列?*/
          ????dequeue(){
          ????????this.queue.shift()
          ????}
          ????/*?獲取隊列長度?*/
          ????size(){
          ????????return?this.queue.length
          ????}
          ????/*?判斷是否為空?*/
          }

          css


          . 問題一:什么是vw+vh布局?有哪些有優(yōu)點?有哪些缺陷?

          解答:

          1什么是什么是vw/vh

          css3中引入了一個新的單位vw/vh,與視圖窗口有關(guān),vw表示相對于視圖窗口的寬度,vh表示相對于視圖窗口高度,除了vw和vh外,還有vmin和vmax兩個相關(guān)的單位。各個單位具體的含義如下:
          單位含義vw相對于視窗的寬度,視窗寬度是100vwvh相對于視窗的高度,視窗高度是100vhvminvw和vh中的較小值vmaxvw和vh中的較大值;
          這里我們發(fā)現(xiàn)視窗寬高都是100vw/100vh,那么vw或者vh,下簡稱vw,很類似百分比單位。vw和%的區(qū)別為:
          單位含義%大部分相對于祖先元素,也有相對于自身的情況比如(border-radius、translate等)vw/vh相對于視窗的尺寸
          從對比中我們可以發(fā)現(xiàn),vw單位與百分比類似,單確有區(qū)別,前面我們介紹了百分比單位的換算困難,這里的vw更像"理想的百分比單位"。任意層級元素,在使用vw單位的情況下,1vw都等于視圖寬度的百分之一。

          2vw單位換算

          同樣的,如果要將px換算成vw單位,很簡單,只要確定視圖的窗口大小(布局視口),如果我們將布局視口設(shè)置成分辨率大小,比如對于iphone6/7 375*667的分辨率,那么px可以通過如下方式換算成vw:

          1px?=?(1/375)*100?vw

          3缺陷

          1 絕大多數(shù)的瀏覽器支持vw單位,但是ie9-11不支持vmin和vmax,考慮到vmin和vmax單位不常用,vw單位在絕大部分高版本瀏覽器內(nèi)的支持性很好,但是opera瀏覽器整體不支持vw單位,如果需要兼容opera瀏覽器的布局,不推薦使用vw。

          2 由于是相對手機(jī)窗口,針對不同的手機(jī)視圖大小不同,所以需要對單位進(jìn)行換算處理。

          . 問題二:什么是rem布局?rem布局的缺陷。

          答:

          rem布局

          rem是一個靈活的、可擴(kuò)展的單位,由瀏覽器轉(zhuǎn)化像素并顯示。與em單位不同,rem單位無論嵌套層級如何,都只相對于瀏覽器的根元素(HTML元素)的font-size。默認(rèn)情況下,html元素的font-size為16px,所以:
          1 rem = 12px
          為了計算方便,通??梢詫tml的font-size設(shè)置成:

          html{?font-size:?62.5%?}

          這種情況下:
          1 rem = 10px
          rem單位都是相對于根元素html的font-size來決定大小的,根元素的font-size相當(dāng)于提供了一個基準(zhǔn),當(dāng)頁面的size發(fā)生變化時,只需要改變font-size的值,那么以rem為固定單位的元素的大小也會發(fā)生響應(yīng)的變化。因此,如果通過rem來實現(xiàn)響應(yīng)式的布局,只需要根據(jù)視圖容器的大小,動態(tài)的改變font-size即可。

          rem布局缺陷

          1 在響應(yīng)式布局中,必須通過js來動態(tài)控制根元素font-size的大小。
          1 css樣式和js代碼有一定的耦合性。且必須將改變font-size的代碼放在css樣式之前

          . 問題三:怎么讓Chrome支持小于12px 的文字

          谷歌瀏覽器默認(rèn)最小字體為12px,若想讓chorme支持12px字體,只需要用css3屬性transform就可以

          ??例子:在谷歌瀏覽器寫出10px字體

          transform:scale(0.5);
          font-size:20px;

          搞定收工~~~

          . 問題四:透明度opacity和rgba的區(qū)別

          opacity

          取值在0到1之間,0表示完全透明,1表示完全不透明。

          .box{opacity:?0.5;}

          rgba

          rgba中的R表示紅色,G表示綠色,B表示藍(lán)色,三種顏色的值都可以是正整數(shù)或百分?jǐn)?shù)。A表示Alpha透明度。取值0~1之間,類似opacity。

          .box{background:?rgba(255,0,0,0.5);}

          rgba和opacity的區(qū)別
          rgba()和opacity都能實現(xiàn)透明效果,但最大的不同是opacity作用于元素,以及元素內(nèi)的所有內(nèi)容的透明度,而rgba()只作用于元素的顏色或其背景色。

          . 問題五:position的屬性值有哪些?

          absolute ? ?
          生成絕對定位的元素,相對于 static 定位以外的第一個父元素進(jìn)行定位。

          元素的位置通過 "left", "top", "right" 以及 "bottom" 屬性進(jìn)行規(guī)定。

          fixed ? ?
          生成絕對定位的元素,相對于瀏覽器窗口進(jìn)行定位。

          元素的位置通過 "left", "top", "right" 以及 "bottom" 屬性進(jìn)行規(guī)定。

          relative ? ?
          生成相對定位的元素,相對于其正常位置進(jìn)行定位。因此,"left:20" 會向元素的 LEFT 位置添加 20 像素。

          static
          默認(rèn)值。沒有定位,元素出現(xiàn)在正常的流中(忽略 top, bottom, left, right 或者 z-index 聲明)。
          inherit ? ?
          規(guī)定應(yīng)該從父元素繼承 position 屬性的值。

          . 問題六:display的屬性值有哪些?

          none(元素不會被顯示);

          block(元素將顯示為塊級元素,元素前后會帶有換行符);

          inline(元素會被顯示為內(nèi)聯(lián)元素,元素前后沒有換行符);

          inline-block(行內(nèi)塊元素。CSS2.1新增的值);

          table(元素會作為塊級表格來顯示,類似table,表格前后帶有換行符);

          table-row(元素會作為一個表格行顯示,類似tr);

          table-cell(元素會作為一個表格單元格顯示,類似td和th)

          flex 彈性盒結(jié)構(gòu)

          gird 網(wǎng)格結(jié)構(gòu)

          . 問題七:垂直水平居中的方案有哪些(盡量說全面一些)

          position absolute 50% + 負(fù)margin -50%

          .container?{
          ????position:?relative;
          }
          .box?{
          ????position:?absolute;
          ????top:?50%;
          ????left:?50%;
          ????margin-top:?-50%;
          ????margin-left:?-50%;
          }

          position absolute ?50% + transform -50%

          .container?{
          ????position:?relative;
          }
          .box?{
          ????position:?absolute;
          ????top:?50%;
          ????left:?50%;
          ????transform:?translate(-50%,?-50%);
          }

          css-table

          /*?此處引用上面的公共代碼?*/
          .container?{
          ????display:?table-cell;
          ????text-align:?center;
          ????vertical-align:?middle;
          }
          .box?{
          ????display:?inline-block;
          }

          flex


          /*?此處引用上面的公共代碼?*/
          .container?{
          ????display:?flex;
          ????justify-content:?center;
          ????align-items:?center;
          }
          .box-center?{
          ????text-align:?center;
          }

          grid

          /*?此處引用上面的公共代碼?*/
          .container?{
          ????display:?grid;
          ????justify-items:?center;
          ????align-items:?center;
          }
          .box-center?{
          ????text-align:?center;
          }

          vue 篇


          . 問題1:vue各個生命周期及其作用

          1.初始化

          beforeCreate:大vue已經(jīng)初始化,只是數(shù)據(jù)初始化與事件系統(tǒng)構(gòu)建尚未形成,不能獲取DOM節(jié)點(沒有data,沒有el)
          使用場景:因為此時data和methods都拿不到,所以通常在實例以外使用。
          created:實例已經(jīng)創(chuàng)建,仍然不能獲取DOM節(jié)點(有data,沒有el)
          使用場景:模板渲染成html前調(diào)用,此時可以獲取data和methods, 可以初始化進(jìn)行數(shù)據(jù)請求,得到渲染數(shù)據(jù),,異步操作可以放在這里
          2 掛載
          beforeMount是個過渡階段,此時依然獲取不到具體的DOM節(jié)點,但是vue掛載的根節(jié)點已經(jīng)創(chuàng)建(有data,有el)
          mounted:組件掛載完成,數(shù)據(jù)和DOM都已經(jīng)被渲染出來了
          使用場景:模板渲染成html后調(diào)用,通常是初始化頁面完成后再對數(shù)據(jù)和DOM做一些操作,需要操作DOM的方法可以放在這里
          3.更新
          beforeUpdate:檢測到數(shù)據(jù)更新時,但在DOM更新前執(zhí)行
          updated:更新結(jié)束后執(zhí)行
          使用場景:需要對數(shù)據(jù)更新做統(tǒng)一處理的;如果需要區(qū)分不同的數(shù)據(jù)更新操作可以使用$nextTick
          4.銷毀
          beforeDestroy:當(dāng)要銷毀vue實例時,在銷毀前執(zhí)行
          destroyed:銷毀vue實例時執(zhí)行

          父子組件mounted和destroyed順序

          beforeMount執(zhí)行順序 先父后子

          mounted執(zhí)行順序,先子后父

          beforeDestroy 執(zhí)行順序,先父后子

          destroyed 執(zhí)行順序 , 先子后父

          . 問題2:vue3的雙向綁定原理,與vue2.0比起來有那些優(yōu)勢?

          vue3.0 的數(shù)據(jù)綁定原理 proxy 對象
          vue3.0 于 Proxy 的 observer 實現(xiàn), 代替了Vue 2 系列中基于 Object.defineProperty 做為響應(yīng)式原理

          感興趣的同學(xué)可以看一下筆者的vue3.0響應(yīng)式原理詳解

          傳送門:vue3.0 響應(yīng)式原理(超詳細(xì))

          優(yōu)勢:
          1 對屬性的添加、刪除動作的監(jiān)測;
          2 對數(shù)組基于下標(biāo)的修改、對于 .length 修改的監(jiān)測;
          3 對 Map、Set、WeakMap 和 WeakSet 的支持;;
          4 vue3 對依賴收集用的是weaMap,WeakSet,保持了對鍵名所引用的對象的弱引用,即垃圾回收機(jī)制不將該引用考慮在內(nèi),一旦不再需要,WeakMap 里面的鍵名對象和所對應(yīng)的鍵值對會自動消失,不用手動刪除引用。
          5 vue2.0 初始化data時候,對于對象等引用數(shù)據(jù)類型,進(jìn)行了遞歸處理,也就是對于一些掛載在data上屬性,但是并沒有用到的屬性,也同樣做了響應(yīng)式處理,而vue3.0之后訪問到父級屬性之后,在進(jìn)行下一層track,也就是說初始化data時候無需把大量性能浪費在遞歸上。

          . 問題3:vue路由衛(wèi)士?

          vue中路由守衛(wèi)一共有三種,一個全局路由守衛(wèi),一個是組件內(nèi)路由守衛(wèi),一個是router獨享守衛(wèi)。

          一、全局路由守衛(wèi)

          只要全局路由變化,就會觸發(fā)全局的路由守衛(wèi)。
          全局路由守衛(wèi)有個兩個:一個是全局前置守衛(wèi),一個是全局后置守衛(wèi)。

          router.beforeEach((to,?from,?next)?=>?{
          ????console.log(to)?=>?//?到哪個頁面去?
          ????console.log(from)?=>?//?從哪個頁面來?
          ????next()?=>?//?一個回調(diào)函數(shù)
          }
          router.afterEach(to,from)?=?{}

          next(false): 中斷當(dāng)前的導(dǎo)航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到 from 路由對應(yīng)的地址,next('/') 或者 next({ path: '/' }): 跳轉(zhuǎn)到一個不同的地址。當(dāng)前的導(dǎo)航被中斷,然后進(jìn)行一個新的導(dǎo)航。你可以向 next 傳遞任意位置對象,且允許設(shè)置諸如 replace: true、name: 'home' 之類的選項以及任何用在 router-link 的 to prop 或 router.push 中的選項.

          二、組件路由守衛(wèi)

          //?跟methods:?{}等同級別書寫,組件路由守衛(wèi)是寫在每個單獨的vue文件里面的路由守衛(wèi)
          beforeRouteEnter?(to,?from,?next)?{
          ????//?注意,在路由進(jìn)入之前,組件實例還未渲染,所以無法獲取this實例,只能通過vm來訪問組件實例
          ????next(vm?=>?{})
          }
          beforeRouteUpdate?(to,?from,?next)?{
          ????//?同一頁面,刷新不同數(shù)據(jù)時調(diào)用,
          }
          beforeRouteLeave?(to,?from,?next)?{
          ????//?離開當(dāng)前路由頁面時調(diào)用
          }

          三、路由獨享守衛(wèi)
          路由獨享守衛(wèi)是在路由配置頁面單獨給路由配置的一個守衛(wèi)

          export?default?new?VueRouter({
          ????routes:?[
          ????????{
          ????????????path:?'/',
          ????????????name:?'home',
          ????????????component:?'Home',
          ????????????beforeEnter:?(to,?from,?next)?=>?{
          ???????????????//?...
          ????????????}
          ????????}
          ????]
          })

          . 問題4:vue 中watch和computed區(qū)別?

          watch側(cè)重點是對數(shù)據(jù)更新所產(chǎn)生的依賴追蹤,而computed側(cè)重點是對數(shù)據(jù)的緩存與處理引用,這就是watch和computed本質(zhì)的區(qū)別 ,computed可以看作一種特殊的data數(shù)據(jù)類型 ,它內(nèi)部進(jìn)行了二次依賴收集 ,第一次依賴收集是引用computed屬性值,而進(jìn)行的依賴收集 ,第二次是對computed內(nèi)部是否關(guān)聯(lián)data或者props的屬性,而又進(jìn)行的一次依賴收集。

          下面我們按照vue3.0兩個例子,來分別兩者之前在流程上有什么區(qū)別。

          watch

          <div?id="app">
          ???<p>{{?count?}}p>
          ???<button?@input="add"?>addbutton>
          div>
          <script>
          const?{?reactive,?watch,?toRefs?}?=?Vue
          Vue.createApp({
          ??setup(){
          ????const?state?=?reactive({
          ???????count:1,
          ????})
          ????const?add?=?()?=>?state.count++
          ????watch(state.count,(count,?prevCount)?=>?{
          ???????console.log('新的count='?,?count?)
          ????})
          ????return?{
          ??????...toRefs(state),
          ??????add
          ????}
          ??}
          }).mount('#app')
          script>

          從上述例子我們看出,當(dāng)點擊add后count變化 ,而是 watch作用就是,追蹤到count變化 ,而促使回調(diào)函數(shù)執(zhí)行。我們用一張流程圖來解析整個流程。

          computed

          <div?id="app">
          ???<p>{{?plusOne?}}p>
          ???<button?@input="add"?>addbutton>
          div>

          <script>
          Vue.createApp({
          ??data:?()?=>?({
          ????number:?1
          ??}),
          ??computed:?{
          ????plusOne()?{
          ??????return?this.number?+?1
          ????}??
          ??},
          ??methods:?{
          ????add(){
          ??????this.number++
          ????}
          ??}
          }).mount('#app')
          script>

          當(dāng)我們點擊add改變的是number,但是引用過this.number的computed也更新了新的值 ,頁面更新,我們可以看出 plusOne計算屬性可以看作一個對number緩存的數(shù)據(jù)類型,data下的number收集了plusOne依賴項,同樣plusOne也收集了{(lán){ plusOne }}的依賴促使更新視圖,我們用一張流程圖來解析整個流程。

          如果想要看原理解析請看筆者的文章

          傳送門 vue3.0 watch 和 computed源碼解析(舉例圖解)

          . 問題5:vue中data為什么要是個函數(shù)?

          vue中data必須是一個函數(shù)是和js本身特性有關(guān)。

          我們做vue項目的時候,所有的vue組件都是基于大vue實例化的,我們可以用一個簡單例子來解釋一下:

          function?Vue(){

          }
          Vue.prototype.data?=?{
          ????name:'jack',
          ????age:22,
          }
          var?componentA?=?new?Vue();
          var?componentB?=?new?Vue();
          componentA.data.age=55;
          console.log(componentA,componentB)

          此時,componentA 和 componentB data之間指向了同一個內(nèi)存地址,age 都變成了 55, 導(dǎo)致了問題!
          接下來很好解釋為什么 vue 組件需要 function 了:

          function?Vue(){
          ?this.data?=?this.data()
          }
          Vue.prototype.data?=?function?(){
          ????return?{
          ????name:'jack',
          ????age:22,
          }
          }
          var?componentA?=?new?Vue();
          var?componentB?=?new?Vue();
          componentA.data.age=55;
          console.log(componentA,componentB)

          componentA 和 componentB data之間相互獨立, age 分別是 55 和 22
          當(dāng)data是一個方法的時候,每一個實例化組件都會形成一個獨立的data對象,相互之間沒有影響。

          react 篇


          . 問題1:setState是同步的還是異步的?

          對于這個問題,筆者自己總結(jié)了一下:對于setState是同步還是異步,對于整個react代碼執(zhí)行上下文來說,setState是同步的,但是setState觸發(fā)以后,并不一定得到新的數(shù)據(jù),這里有一個react有一個batchUpdate批量更新的概念。

          我們來看一個例子??:

          class?Example?extends?React.Component?{
          ??constructor()?{
          ????super();
          ????this.state?=?{
          ??????val:?0
          ????};
          ??}

          ??componentDidMount()?{
          ????this.setState({val:?this.state.val?+?1});
          ????console.log(this.state.val);????//?第?1?次?log

          ????this.setState({val:?this.state.val?+?1});
          ????console.log(this.state.val);????//?第?2?次?log

          ????setTimeout(()?=>?{
          ??????this.setState({val:?this.state.val?+?1});
          ??????console.log(this.state.val);??//?第?3?次?log

          ??????this.setState({val:?this.state.val?+?1});
          ??????console.log(this.state.val);??//?第?4?次?log
          ????},?0);
          ??}

          ??render()?{
          ????return?null;
          ??}
          };

          答案是:0 0 2 3

          在React的setState函數(shù)實現(xiàn)中,會根據(jù)一個變量isBatchingUpdates判斷是直接更新this.state還是放到隊列中回頭再說,而isBatchingUpdates默認(rèn)是false,也就表示setState會同步更新this.state,但是,有一個函數(shù)batchedUpdates,這個函數(shù)會把isBatchingUpdates修改為true,而當(dāng)React在調(diào)用事件處理函數(shù)之前就會調(diào)用這個batchedUpdates,造成的后果,就是由React控制的事件處理過程setState不會同步更新this.state 。

          . 問題2:介紹一下 react-hooks API及其如何使用?

          usestate 無狀態(tài)組件的state

          useCallback,useMemo 性能優(yōu)化利器.

          useContext 可以使用操縱react context.

          useEffect ,useLayoutEffect 副作用鉤子 可以替代class聲明組件中的聲明周期 .useLayoutEffect 在瀏覽器渲染之前 , effect在瀏覽器渲染之后

          useReducer 功能可以參考redux

          useRef 可以獲取元素和組件實例,還可以緩存數(shù)據(jù)

          詳細(xì)的react-hooks使用可以戳??

          傳送門:react-hooks如何使用?

          webpack篇


          . 問題一:webpack性能優(yōu)化?

          打包的時間和打包之后文件的體積是影響webpack性能的主要因素。所以我們可以從這兩個方面入手,來優(yōu)化webpack性能。

          1合理使用loader
          用 include 或 exclude 來幫我們避免不必要的轉(zhuǎn)譯,優(yōu)化loader的管轄范圍。

          2緩存babel編譯過的文件

          loader: 'babel-loader?cacheDirectory=true'
          如上,我們只需要為 loader 增加相應(yīng)的參數(shù)設(shè)定。選擇開啟緩存將轉(zhuǎn)譯結(jié)果緩存至文件系統(tǒng),可以提交babel-loader的工作效率。

          3 ?DllPlugin類庫引入

          DllPlugin 是基于 Windows 動態(tài)鏈接庫(dll)的思想被創(chuàng)作出來的。這個插件會把第三方庫單獨打包到一個文件中,這個文件就是一個單純的依賴庫。這個依賴庫不會跟著你的業(yè)務(wù)代碼一起被重新打包,只有當(dāng)依賴自身發(fā)生版本變化時才會重新打包。

          4 happypack多進(jìn)程編譯

          我們都知道nodejs是單線程。無法一次性執(zhí)行多個任務(wù)。這樣會使得所有任務(wù)都排隊執(zhí)行。happypack可以根據(jù)cpu核數(shù)優(yōu)勢,建立子進(jìn)程child_process,充分利用多核優(yōu)勢解決這個問題。提高了打包的效率。

          const?HappyPack?=?require('happypack')
          //?手動創(chuàng)建進(jìn)程池
          const?happyThreadPool?=??HappyPack.ThreadPool({?size:?os.cpus().length?})
          module.exports?=?{
          ??module:?{
          ????rules:?[
          ??????...
          ??????{
          ????????test:?/\.js$/,
          ????????//?問號后面的查詢參數(shù)指定了處理這類文件的HappyPack實例的名字
          ????????loader:?'happypack/loader?id=happyBabel',
          ????????...
          ??????},
          ????],
          ??},
          ??plugins:?[
          ????...
          ????new?HappyPack({
          ??????//?這個HappyPack的“名字”就叫做happyBabel,和樓上的查詢參數(shù)遙相呼應(yīng)
          ??????id:?'happyBabel',
          ??????//?指定進(jìn)程池
          ??????threadPool:?happyThreadPool,
          ??????loaders:?['babel-loader?cacheDirectory']
          ????})
          ??],
          }

          `
          happypack成功,啟動了三個進(jìn)程編譯。加快了loader的加載速度。

          5 scope Hoisting

          scope Hoisting的作用是分析模塊之前的依賴關(guān)系 , 把打包之后的公共模塊合到同一個函數(shù)中去。它會代碼體積更小,因為函數(shù)申明語句會產(chǎn)生大量代碼;代碼在運行時因為創(chuàng)建的函數(shù)作用域更少了,內(nèi)存開銷也隨之變小。

          const?ModuleConcatenationPlugin?=?require('webpack/lib/optimize/ModuleConcatenationPlugin');

          module.exports?=?{
          ??resolve:?{
          ????//?針對?Npm?中的第三方模塊優(yōu)先采用?jsnext:main?中指向的?ES6?模塊化語法的文件
          ????mainFields:?['jsnext:main',?'browser',?'main']
          ??},
          ??plugins:?[
          ????//?開啟?Scope?Hoisting
          ????new?ModuleConcatenationPlugin(),
          ??],
          };

          6 ?tree Shaking 刪除冗余代碼

          Tree-Shaking可以通過分析出import/exports依賴關(guān)系。對于沒有使用的代碼。可以自動刪除。這樣就減少了項目的體積。

          舉個例子??:

          import { a, b } from './pages'
          a()
          pages 文件里,我雖然導(dǎo)出了兩個頁面:
          export const a = ()=>{ console.log(666) }
          export const b = ()=>{ console.log(666) }
          所以打包的結(jié)果會保留這部分:
          export const a = ()=>{ console.log(666) }
          b方法直接刪掉,這就是 Tree-Shaking 幫我們做的事情。刪掉了沒有用到的代碼。

          7 按需加載

          像vue 和 react spa應(yīng)用,首次加載的過程中,由于初始化要加載很多路由,加載很多組件頁面。會導(dǎo)致 首屏?xí)r間 非常長。一定程度上會影響到用戶體驗。所以我們需要換一種按需加載的方式。一次只加載想要看到的內(nèi)容

          require.ensure 形式

          const?getComponent?=>?(location,?cb)?{
          ??require.ensure([],?(require)?=>?{
          ????cb(null,?require('../pages/AComponent').default)
          ??},?'a')
          }
          "/a"?getComponent={getComponent}>

          import形式

          import?B?from?'@/pages/business/b.vue'
          //按需加載變成了:
          const?B?=?()?=>?import('@/pages/business/b.vue')

          8 按需引用

          不知道大家有沒有體會到,當(dāng)我們用antd等這種UI組件庫的時候。明明只想要用其中的一兩個組件,卻要把整個組件庫連同樣式庫一起引進(jìn)來,就會造成打包后的體積突然增加了好幾倍。為了解決這個問題,我們可以采取按需引入的方式。

          拿antd為例,需要我們在.babelrc文件中這樣聲明,

          {
          "presets":?[
          ???[
          ????"@babel/preset-env",
          ????{
          ??????"targets":?{
          ??????????"chrome":?"67"
          ??????},
          ????"useBuiltIns":?"usage",
          ?????"corejs":?2
          ????}
          ???],
          ????"@babel/preset-react"
          ?],
          ??"plugins":?[
          ??[
          ???"@babel/plugin-transform-runtime",
          ??],
          ??//重點按需引入antd里面的style
          ??[??"import",?{
          ???"libraryName":?"antd",
          ???"libraryDirectory":?"es",
          ???"style":?true
          ??}]
          ?]
          }

          經(jīng)過如上配置之后,我們會發(fā)現(xiàn)體積比沒有處理的要小很多。

          . 問題二:webpack怎么配置多頁面應(yīng)用?

          實際這個問題變相再問webpack,配置多入口和多個html對應(yīng)

          entry 應(yīng)該這么配 ,entry支持 string array object

          {
          ??//入口文件配置?string?|?array?|?object
          ??entry:?{
          ????index:?'./src/index.js',
          ????list:?'./src/list.js',
          ????detail:?'./src/detail.js'
          ??},
          }

          html輸出配置 輸出html需要webpack插件 html-webpack-plugin

          {
          ????plugins:?[
          ????new?htmlWebpackPulgin({
          ??????title:?'hello?我是首頁',
          ??????template:?'./index.html',
          ??????inject:?'head',
          ??????filename:?'index.html',
          ??????chunks:?['index']?//對應(yīng)?index.js
          ????}),
          ????new?htmlWebpackPulgin({
          ??????title:?'hello?我是列表',
          ??????template:?'./index.html',
          ??????inject:?'body',
          ??????filename:?'list.html',
          ??????chunks:?['list']?//?對應(yīng)?list.js
          ????}),
          ????new?htmlWebpackPulgin({
          ??????title:?'hello?我是詳情',
          ??????template:?'./index.html',
          ??????inject:?'body',
          ??????filename:?'detail.html',
          ??????chunks:?['detail']??//對應(yīng)detail.js
          ????})
          ??]
          }

          http篇


          . 問題1:URL請求頁面之后瀏覽器的解析過程

          1.用戶輸入網(wǎng)址,瀏覽器發(fā)起DNS查詢請求,域名解析。

          2.三次握手

          3.建立tcp連接,發(fā)送http請求

          4.服務(wù)器接受到請求,并相應(yīng)http請求

          5.瀏覽器對返回的html進(jìn)行解析,在這期間可能繼續(xù)請求css,js等文件,瀏覽器渲染、構(gòu)建網(wǎng)頁

          6.斷開連接,四次揮手

          7.瀏覽器對頁面進(jìn)行渲染呈現(xiàn)給用戶

          . 問題2:javascript的同源策略

          同源策略是一個重要的安全策略,它用于限制一個origin的文檔或者它加載的腳本如何能與另一個源的資源進(jìn)行交互。它能幫助阻隔惡意文檔,減少可能被攻擊的媒介。

          如果兩個 URL 的 protocol、port (如果有指定的話)和 host 都相同的話,則這兩個 URL 是同源。這個方案也被稱為“協(xié)議/主機(jī)/端口元組”,或者直接是 “元組”。(“元組” 是指一組項目構(gòu)成的整體,雙重/三重/四重/五重/等的通用形式)。

          源的繼承
          在頁面中通過 about:blank 或 javascript: URL 執(zhí)行的腳本會繼承打開該 URL 的文檔的源,因為這些類型的 URLs 沒有包含源服務(wù)器的相關(guān)信息。

          源的修改
          滿足某些限制條件的情況下,頁面是可以修改它的源。腳本可以將 document.domain 的值設(shè)置為其當(dāng)前域或其當(dāng)前域的父域。如果將其設(shè)置為其當(dāng)前域的父域,則這個較短的父域?qū)⒂糜诤罄m(xù)源檢查。

          . 問題3:怎么解決ie瀏覽器對get請求的緩存?

          不知道大家有沒有過一種情況,在低版本ie瀏覽器下,在短暫的時間內(nèi)發(fā)出相同的get情況(比如相同時間請求一個數(shù)據(jù)列表多次),就會發(fā)現(xiàn)請求只發(fā)送了一次,其他的請求都被瀏覽器緩存了,對于這種緩存ajax情況,我們可以在url拼上時間戳,這樣瀏覽器就不會認(rèn)為這是相同的情況,就不會緩存get情況。

          以aixos為例,我們可以在每次發(fā)起請求的時候?qū)et請求加以攔截

          /*?攔截器?*/
          axios.interceptors.request.use(
          ????(config)?=>?{
          ????????const?method???=?config.method?||?'get'
          ????????if?(method.toLowerCase()?===?'get')?{??/*?防止瀏覽器緩存?*/
          ????????????const?url??=?config.url?||?''
          ????????????const?t?=?new?Date().getTime()
          ????????????config.url?=?`${url}${url.indexOf('?')?===?-1???'?'?:?'&'}t=${t}`
          ????????}else?if(method.toLowerCase()?===?'post'){?/*?設(shè)置不同請求頭?*/
          ????????????//...
          ????????}
          ????????return?config
          ????},
          ????(error)?=>?{?
          ????}
          )

          如上,就完美解決了ajax被ie瀏覽器緩存的問題。


          參考文檔

          布局常用解決方案對比(媒體查詢、百分比、rem和vw/vh)
          css中的多種垂直水平居中
          JavaScript內(nèi)存泄露的4種方式及如何避免
          vue路由守衛(wèi)哪幾種?
          Vue組件為什么data必須是一個函數(shù)?
          深入 setState 機(jī)制

          總結(jié)

          希望看到后覺的不錯的小伙伴關(guān)注一波公眾號,定期分享好的技術(shù)文章。


          一大波連載好文章正在路上。。。


          關(guān)注我們


          公眾號ID:前端公蝦米



          冰淇淋里有夏天的味道




          瀏覽 97
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本黄色视频网站片 | 免费观看黄色视频网站在线观看 | 永久免费在线观看不卡黄网站 | 91成人高清 | 激情无码国产 |