整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          2022高頻前端面試題匯總(附答案)

          2022高頻前端面試題匯總(附答案)

          有朋友準(zhǔn)備看看新工作,正好有空,幫忙整理了一下常見的前端面試題,整理的面試題都比較基礎(chǔ),主要面向初中級前端。篇幅有限,有些知識就直接貼文章鏈接了,大家可以自己去看~

          一、CSS篇

          1、什么是 BFC

          BFC(Block Formatting Context)格式化上下文,是 Web 頁面中盒模型布局的 CSS 渲染模式,指一個獨立的渲染區(qū)域或者說是一個隔離的獨立容器。

          形成 BFC 的條件

          • 浮動元素,float 除 none 以外的值
          • 定位元素,position(absolute,fixed)
          • display 為以下其中之一的值 inline-block,table-cell,table-caption
          • overflow 除了 visible 以外的值(hidden,auto,scroll)
          • HTML 就是一個 BFC

          BFC 的特性

          • 內(nèi)部的 Box 會在垂直方向上一個接一個的放置。
          • 垂直方向上的距離由 margin 決定
          • bfc 的區(qū)域不會與 float 的元素區(qū)域重疊。
          • 計算 bfc 的高度時,浮動元素也參與計算
          • bfc 就是頁面上的一個獨立容器,容器里面的子元素不會影響外面元素。


          2、什么是盒模型

          CSS3中的盒模型有以下兩種:標(biāo)準(zhǔn)盒子模型、IE盒子模型

          盒模型都是由四個部分組成的,分別是margin、border、padding和content。

          在標(biāo)準(zhǔn)盒模型性中

          盒子在網(wǎng)頁中實際占用:
          寬=width + padding2 + border2 + margin2
          高=height + padding2 + border2 + margin2

          盒模型實際大小:
          寬=width + padding2 + border2
          高=height + padding2 + border2

          在IE盒模型性中

          盒子在網(wǎng)頁中實際占用:
          寬=width + margin2
          高=height + margin2

          盒模型實際大小:
          寬=width
          高=height

          可以通過修改元素的box-sizing屬性來改變元素的盒模型:

          • box-sizeing: content-box表示標(biāo)準(zhǔn)盒模型
          • box-sizeing: border-box表示IE盒模型


          3、未知高度元素垂直居中的幾種方案

          當(dāng)需要垂直居中的元素高度未知時,一般采用一下幾種方案實現(xiàn)垂直居中:

          使用絕對定位和transform

          css復(fù)制代碼.parent {
              position: relative;
              width: 100%;
              height: 400px;
          }
          .children {
              position: absolute;
              top: 50%;
              transform: translate(0, -50%);
          }
          

          flex實現(xiàn)垂直居中(最常用的)

          css復(fù)制代碼.parent {
              display: flex;
              align-items: center;
              justify-content: center;
              width: 100%;
              height: 400px;
              background: #fff;
          }
          .children {
              background: red;
          }
          

          通過table屬性

          css復(fù)制代碼<div class="parent">
              <div class="children">
                  <div>test</div>
              </div>
          </div>
          
          .parent {
              display: table;
              text-align:center;
          }
          
          .children {
              background: #ccc;
              display: table-cell;
              vertical-align: middle;
          }
          
          .child div {
              width: 300px;
              height: 150px;
              background: red;
              margin: 0 auto;
          }
          


          4、CSS3中有哪些新特性

          • 新增各種CSS選擇器
          • 圓角 (border-radius:8px)
          • 多列布局 (multi-column layout)
          • 陰影和反射 (Shadoweflect)
          • 文字特效 (text-shadow)
          • 文字渲染 (Text-decoration)
          • 線性漸變 (gradient)
          • 旋轉(zhuǎn) (transform)
          • 增加了旋轉(zhuǎn),縮放,定位,傾斜,動畫,多背景

          5、什么是CSS 預(yù)處理器 / 后處理器?大家為什么要使用他們?

          預(yù)處理器:例如LESS、Sass、Stylus,用來預(yù)編譯Sass或less,增強(qiáng)了css代碼的復(fù)用性,還有層級、mixin、變量、循環(huán)、函數(shù)等,具有很方便的UI組件模塊化開發(fā)能力,極大的提高工作效率。

          后處理器:例如PostCSS,通常被視為在完成的樣式表中根據(jù)CSS規(guī)范處理CSS,讓其更有效;目前最常做的是給CSS屬性添加瀏覽器私有前綴,實現(xiàn)跨瀏覽器兼容性的問題。

          CSS 預(yù)處理器為 CSS 增加一些編程的特性,無需考慮瀏覽器的兼容性問題”,例如你可以在 CSS 中使用變量、簡單的邏輯程序、函數(shù)(如右側(cè)代碼編輯器中就使用了變量$color)等等在編程語言中的一些基本特性,可以讓你的 CSS 更加簡潔、適應(yīng)性更強(qiáng)、可讀性更佳,更易于代碼的維護(hù)等諸多好處。


          6、為什么會出現(xiàn)margin重疊的問題?怎么解決?

          問題描述: 兩個塊級元素的上外邊距和下外邊距可能會合并(折疊)為一個外邊距,其大小會取其中外邊距值大的那個,這種行為就是外邊距折疊。需要注意的是,浮動的元素和絕對定位這種脫離文檔流的元素的外邊距不會折疊。重疊只會出現(xiàn)在垂直方向。

          計算原則: 折疊合并后外邊距的計算原則如下:

          • 如果兩者都是正數(shù),那么就取最大者
          • 如果是一正一負(fù),就會正值減去負(fù)值的絕對值
          • 兩個都是負(fù)值時,用0減去兩個中絕對值大的那個

          解決辦法: 對于折疊的情況,主要有兩種:兄弟之間重疊和父子之間重疊

          (1)兄弟之間重疊

          • 底部元素變?yōu)樾袃?nèi)盒子:display: inline-block
          • 底部元素設(shè)置浮動:float
          • 底部元素的position的值為absolute/fixed

          (2)父子之間重疊

          • 父元素加入:overflow: hidden
          • 父元素添加透明邊框:border:1px solid transparent
          • 子元素變?yōu)樾袃?nèi)盒子:display: inline-block
          • 子元素加入浮動屬性或定位


          7、flex布局

          flex知識點的話,建議大家去看阮一峰老師的文章,看完應(yīng)該就明白了

          Flex 布局教程:語法篇
          Flex 布局教程:實例篇


          8、移動端媒體查詢,rem, vw的理解

          @media媒體查詢是針對不同的媒體類型定義不同的樣式,特別是響應(yīng)式頁面,可以針對不同屏幕的大小,編寫多套樣式,從而達(dá)到自適應(yīng)效果,代碼如下:

          css復(fù)制代碼@media screen and (max-width: 720px) {
              body {
                  background-color: #6633FF;
              }
          }
          
          @media screen and (max-width: 640px) {
              body {
                  background-color: #00FF66;
              }
          }
          /*
            上述的代碼分別對分辨率在0~640px以及640px~720px的屏幕設(shè)置了不同的背景顏色。
          */
          

          rem 是一個靈活的可擴(kuò)展的單位,由瀏覽器轉(zhuǎn)化像素并顯示。與em單位不同,rem單位無論嵌套層級如何,都只相對于瀏覽器的根元素(HTML元素)的font-size

          由于viewport單位得到眾多瀏覽器的兼容,lib-flexible這個過渡方案已經(jīng)可以放棄使用,不管是現(xiàn)在的版本還是以前的版本,都存有一定的問題。建議大家開始使用viewport, 代碼如下:

          js復(fù)制代碼(function flexible (window, document) {
            var docEl=document.documentElement
            var dpr=window.devicePixelRatio || 1
          
            // adjust body font size
            function setBodyFontSize () {
              if (document.body) {
                document.body.style.fontSize=(12 * dpr) + 'px'
              } else {
                document.addEventListener('DOMContentLoaded', setBodyFontSize)
              }
            }
            setBodyFontSize();
          
            // set 1rem=viewWidth / 10
            function setRemUnit () {
              var rem=docEl.clientWidth / 10
              docEl.style.fontSize=rem + 'px'
            }
          
            setRemUnit()
          
            // reset rem unit on page resize
            window.addEventListener('resize', setRemUnit)
            window.addEventListener('pageshow', function (e) {
              if (e.persisted) {
                setRemUnit()
              }
            })
          
            // detect 0.5px supports
            if (dpr >=2) {
              var fakeBody=document.createElement('body')
              var testElement=document.createElement('div')
              testElement.style.border='.5px solid transparent'
              fakeBody.appendChild(testElement)
              docEl.appendChild(fakeBody)
              if (testElement.offsetHeight===1) {
                docEl.classList.add('hairlines')
              }
              docEl.removeChild(fakeBody)
            }
          }(window, document))
          

          什么是vw/vh ?

          vw/vh是一個相對單位(類似于em,rem)

          • vw:viewport width 視口寬度單位
          • vh:viewport height 視口高度單位

          相對視口的尺寸計算結(jié)果

          • 1vw=1/100視口寬度
          • 1vh=1/100視口高度


          9、移動端1px解決方案

          1px的問題經(jīng)常出現(xiàn)在移動端邊框設(shè)置上,會導(dǎo)致設(shè)置1px邊框看起來較粗,影響用戶體驗,對于boder的1px問題,可以通過偽元素 + transform來解決, 代碼如下:

          css復(fù)制代碼/* 手機(jī)端實現(xiàn)真正的一像素邊框 */
          .border-1px, 
          .border-bottom-1px, 
          .border-top-1px, 
          .border-left-1px, 
          .border-right-1px {
              position: relative;
          }
          
          /* 線條顏色 */
          .border-1px::after, 
          .border-bottom-1px::after, 
          .border-top-1px::after, 
          .border-left-1px::after, 
          .border-right-1px::after {
              background-color: #000;
          }
          
          /* 底邊邊框一像素 */
          .border-bottom-1px::after {
              content: "";
              position: absolute;
              left: 0;
              bottom: 0;
              width: 100%;
              height: 1px;
              transform-origin: 0 0;
          }
          
          /* 上邊邊框一像素 */
          .border-top-1px::after {
              content: "";
              position: absolute;
              left: 0;
              top: 0;
              width: 100%;
              height: 1px;
              transform-origin: 0 0;
          }
          
          /* 左邊邊框一像素 */
          .border-left-1px::after {
              content: "";
              position: absolute;
              left: 0;
              top: 0;
              width: 1px;
              height: 100%;
              transform-origin: 0 0;
          }
          
          /* 右邊邊框1像素 */
          .border-right-1px::after {
              content: "";
              position: absolute;
              right: 0;
              top: 0;
              width: 1px;
              height: 100%;
              transform-origin: 0 0;
              box-sizing: border-box;
          }
          
          /* 邊框一像素 */
          .border-1px::after {
              content: "";
              position: absolute;
              left: 0;
              top: 0;
              width: 100%;
              height: 100%;
              border: 1px solid gray;
              box-sizing: border-box;
          }
          
          /* 設(shè)備像素比 */
          /* 顯示屏最小dpr為2 */
          @media (-webkit-min-device-pixel-ratio: 2) {
              .border-bottom-1px::after, .border-top-1px::after {
                  transform: scaleY(0.5);
              }
          
              .border-left-1px::after, .border-right-1px::after {
                  transform: scaleX(0.5);
              }
          
              .border-1px::after {
                  width: 200%;
                  height: 200%;
                  transform: scale(0.5);
                  transform-origin: 0 0;
              }
          }
          
          /* 設(shè)備像素比 */
          @media (-webkit-min-device-pixel-ratio: 3)  {
              .border-bottom-1px::after, .border-top-1px::after {
                  transform: scaleY(0.333);
              }
          
              .border-left-1px::after, .border-right-1px::after {
                  transform: scaleX(0.333);
              }
          
              .border-1px::after {
                  width: 300%;
                  height: 300%;
                  transform: scale(0.333);
                  transform-origin: 0 0;
              }
          }
          


          10、IOS全面屏安全區(qū)域問題

          iOS 11

          css復(fù)制代碼padding-top: constant(safe-area-inset-top);
          padding-right: constant(safe-area-inset-right);
          padding-bottom: constant(safe-area-inset-bottom);
          padding-left: constant(safe-area-inset-left);
          

          iOS 11.2+

          css復(fù)制代碼padding-top: env(safe-area-inset-top);
          padding-right: env(safe-area-inset-right);
          padding-bottom: env(safe-area-inset-bottom);
          padding-left: env(safe-area-inset-left);
          


          11、圖片變形問題如何解決

          如果圖片設(shè)置的是背景圖

          css復(fù)制代碼background-size: cover;
          

          如果是img標(biāo)簽圖片

          css復(fù)制代碼object-fit: cover;
          


          12、css常見布局實現(xiàn)

          可參考:常見的CSS布局


          二、Javascript基礎(chǔ)

          1、JavaScript數(shù)據(jù)類型

          JavaScript一共有8種數(shù)據(jù)類型

          七種基本數(shù)據(jù)類型:Undefined、Null、Boolean、Number、String、Symbol(es6新增)和BigInt(es10新增)

          一種復(fù)雜數(shù)據(jù)類型:Object 里面包含 Function、Array、Date等

          2、JavaScript判斷數(shù)據(jù)類型的幾種方法

          typeof

          js復(fù)制代碼/*
            優(yōu)點:能夠快速區(qū)分基本數(shù)據(jù)類型
            缺點:不能將Object、Array和Null區(qū)分,都返回object
          */
          console.log(typeof 1);               // number
          console.log(typeof NaN);             // number
          console.log(typeof true);            // boolean
          console.log(typeof 'mc');            // string
          console.log(typeof Symbol)           // function
          console.log(typeof function(){});    // function
          console.log(typeof console.log());   // function
          console.log(typeof []);              // object 
          console.log(typeof {});              // object
          console.log(typeof null);            // object
          console.log(typeof undefined);       // undefined
          

          instanceof

          js復(fù)制代碼/*
            優(yōu)點:能夠區(qū)分Array、Object和Function,適合用于判斷自定義的類實例對象
            缺點:Number,Boolean,String基本數(shù)據(jù)類型不能判斷
          */
          console.log(1 instanceof Number);                    // false
          console.log(true instanceof Boolean);                // false 
          console.log('str' instanceof String);                // false  
          console.log([] instanceof Array);                    // true
          console.log(function(){} instanceof Function);       // true
          console.log(function(){} instanceof Object);         // true
          console.log({} instanceof Function);                 // false
          console.log({} instanceof Object);                   // true
          
          js復(fù)制代碼/*
            優(yōu)點:精準(zhǔn)判斷數(shù)據(jù)類型
            缺點:寫法繁瑣不容易記,推薦進(jìn)行封裝后使用
          */
          const toString=Object.prototype.toString;
          console.log(toString.call(1));                      // [object Number]
          console.log(toString.call(true));                   // [object Boolean]
          console.log(toString.call('mc'));                   // [object String]
          console.log(toString.call([]));                     // [object Array]
          console.log(toString.call({}));                     // [object Object]
          console.log(toString.call(function(){}));           // [object Function]
          console.log(toString.call(undefined));              // [object Undefined]
          console.log(toString.call(null));                   // [object Null]
          


          3、intanceof 操作符的實現(xiàn)原理及實現(xiàn)

          js復(fù)制代碼function instanceOf(left, right) {
              let proto=left.__proto__
              let prototype=right.prototype
              while (true) {
                  if (proto===null) return false
                  if (proto===prototype) return true
                  proto=proto.__proto__
              }
          }
          


          4、數(shù)組常用操作方法

          • push():在末尾添加一個或多個元素,修改原數(shù)組,返回值,數(shù)組新的長度
          • pop():刪除數(shù)組最后一個元素,無參數(shù),修改原數(shù)組,返回值,刪除元素的值
          • unshift():向數(shù)組的開頭添加一個或者多個元素,修改原數(shù)組,返回值,數(shù)組新的長度
          • shift():刪除數(shù)組的第一個元素,數(shù)組長度減1,無參數(shù),修改原數(shù)組,返回值,刪除元素的值
          • reverse():顛倒數(shù)組中元素的順序,無參數(shù),修改原數(shù)組,返回值,新的數(shù)組
          • sort():對數(shù)組的元素進(jìn)行排序,修改原數(shù)組,返回值,新的數(shù)組
          • toString():把數(shù)組轉(zhuǎn)換成字符串,逗號分隔每一項,返回值,一個字符串
          • join():方法用于把數(shù)組中的所有元素轉(zhuǎn)換成一個字符串,返回值,一個字符串
          • concat():連接兩個或多個數(shù)組,不影響原數(shù)組,返回值,一個新的數(shù)組
          • slice():數(shù)組截取slice(begin,end),返回值,返回被截取項目的新數(shù)組
          • splice():數(shù)組刪除splice(第幾個開始,要刪除的個數(shù)),修改原數(shù)組,返回值,返回被刪除項目的新數(shù)組
          • indexOf():從前往后查找數(shù)組元素的索引號,不修改原數(shù)組,返回值,數(shù)組元素的索引號
          • lastIndexOf():從后往前查找數(shù)組元素的索引號,不修改原數(shù)組,返回值,數(shù)組元素的索引號
          • find():用于找出第一個符合條件的數(shù)組成員,返回值,數(shù)組元素
          • findIndex():用于找出第一個符合條件的數(shù)組成員的位置,返回值,索引號
          • includes():判斷某個數(shù)組是否包含給定的值

          5、數(shù)組去重

          除了es6的new Set()去重外,可以通過以下幾種方法實現(xiàn)數(shù)組去重

          js復(fù)制代碼// 利用filter去實現(xiàn)
          Array.prototype.unique1=function() {
              return this.filter((item, index, array)=> {
                  return this.indexOf(item)===index;
              });
          }
          
          js復(fù)制代碼Array.prototype.unique2=function() {
              const n={}, r=[]; // n為hash表,r為臨時數(shù)組
              for (let i=0; i < this.length; i++) {
                  if (!n[this[i]]) { // 如果hash表中沒有當(dāng)前項
                      n[this[i]]=true; //存入hash表
                      r.push(this[i]); //把當(dāng)前數(shù)組的當(dāng)前項push到臨時數(shù)組里面
                  }
              }
              return r;
          }
          
          js復(fù)制代碼// 返回后的數(shù)組順序會亂
          Array.prototype.unique3=function() {
              this.sort();
              const r=[this[0]];
              for (let i=1; i < this.length; i++) {
                  if (this[i] !==this[i - 1]) {
                      r.push(this[i]);
                  }
              }
              return r;
          }
          


          6、執(zhí)行上下文與作用域、作用域鏈

          執(zhí)行上下文(以下簡稱“上下文”)的概念在 JavaScript 中是頗為重要的。變量或函數(shù)的上下文決定了它們可以訪問哪些數(shù)據(jù),以及它們的行為。每個上下文都有一個關(guān)聯(lián)的變量對象(variable object),而這個上下文中定義的所有變量和函數(shù)都存在于這個對象上。雖然無法通過代碼訪問變量對象,但后臺處理數(shù)據(jù)會用到它。

          全局上下文是最外層的上下文。根據(jù) ECMAScript 實現(xiàn)的宿主環(huán)境,表示全局上下文的對象可能不一 樣。在瀏覽器中,全局上下文就是我們常說的window對象,因此所有通過 var 定義的全局變量和函數(shù)都會成為 window 對象的屬性和方法。使用 let 和 const 的頂級聲明不會定義在全局上下文中,但在作用域鏈解析上效果是一樣的。上下文在其所有代碼都執(zhí)行完畢后會被銷毀,包括定義在它上面的所有變量和函數(shù)(全局上下文在應(yīng)用程序退出前才會被銷毀,比如關(guān)閉網(wǎng)頁或退出瀏覽器)。

          每個函數(shù)調(diào)用都有自己的上下文。當(dāng)代碼執(zhí)行流進(jìn)入函數(shù)時,函數(shù)的上下文被推到一個上下文棧上。 在函數(shù)執(zhí)行完之后,上下文棧會彈出該函數(shù)上下文,將控制權(quán)返還給之前的執(zhí)行上下文。ECMAScript 程序的執(zhí)行流就是通過這個上下文棧進(jìn)行控制的。

          上下文中的代碼在執(zhí)行的時候,會創(chuàng)建變量對象的一個作用域鏈(scope chain)。這個作用域鏈決定了各級上下文中的代碼在訪問變量和函數(shù)時的順序。代碼正在執(zhí)行的上下文的變量對象始終位于作用域鏈的最前端。如果上下文是函數(shù),則其活動對象(activation object)用作變量對象。活動對象最初只有一個定義變量:arguments。(全局上下文中沒有這個變量。)作用域鏈中的下一個變量對象來自包含上下文,再下一個對象來自再下一個包含上下文。以此類推直至全局上下文;全局上下文的變量對象始終是作用域鏈的最后一個變量對象。

          代碼執(zhí)行時的標(biāo)識符解析是通過沿作用域鏈逐級搜索標(biāo)識符名稱完成的。搜索過程始終從作用域鏈 的最前端開始,然后逐級往后,直到找到標(biāo)識符。(如果沒有找到標(biāo)識符,那么通常會報錯。) 看一看下面這個例子:

          js復(fù)制代碼var color="blue"; 
           
          function changeColor() { 
           if (color==="blue") { 
               color="red"; 
           } else { 
               color="blue"; 
           } 
          } 
           
          changeColor();
          

          對這個例子而言,函數(shù) changeColor()的作用域鏈包含兩個對象:一個是它自己的變量對象(就 是定義 arguments 對象的那個),另一個是全局上下文的變量對象。這個函數(shù)內(nèi)部之所以能夠訪問變量color,就是因為可以在作用域鏈中找到它。

          此外,局部作用域中定義的變量可用于在局部上下文中替換全局變量。看一看下面這個例子:

          js復(fù)制代碼var color="blue"; 
           
          function changeColor() { 
              let anotherColor="red"; 
          
              function swapColors() { 
                  let tempColor=anotherColor; 
                  anotherColor=color; 
                  color=tempColor; 
                  // 這里可以訪問 color、anotherColor 和 tempColor 
              } 
           
              // 這里可以訪問 color 和 anotherColor,但訪問不到 tempColor 
              swapColors(); 
          } 
           
          // 這里只能訪問 color 
          changeColor();
          

          以上代碼涉及 3 個上下文:全局上下文、changeColor()的局部上下文和 swapColors()的局部 上下文。全局上下文中有一個變量 color 和一個函數(shù) changeColor()。changeColor()的局部上下文中有一個變量 anotherColor 和一個函數(shù) swapColors(),但在這里可以訪問全局上下文中的變量 color。swapColors()的局部上下文中有一個變量 tempColor,只能在這個上下文中訪問到。全局上下文和changeColor()的局部上下文都無法訪問到 tempColor。而在 swapColors()中則可以訪問另外兩個 上下文中的變量,因為它們都是父上下文。下圖展示了這個例子的作用域鏈。

          上圖中的矩形表示不同的上下文。內(nèi)部上下文可以通過作用域鏈訪問外部上下文中的一切,但外 部上下文無法訪問內(nèi)部上下文中的任何東西。上下文之間的連接是線性的、有序的。每個上下文都可以到上一級上下文中去搜索變量和函數(shù),但任何上下文都不能到下一級上下文中去搜索。swapColors()局部上下文的作用域鏈中有 3 個對象:swapColors()的變量對象、changeColor()的變量對象和全局變量對象。swapColors()的局部上下文首先從自己的變量對象開始搜索變量和函數(shù),搜不到就去搜索上一級變量對象。changeColor()上下文的作用域鏈中只有 2 個對象:它自己的變量對象和全局變量對象。因此,它不能訪問 swapColors()的上下文。

          7、說一下你對前端閉包的理解

          閉包是指有權(quán)訪問另外一個函數(shù)作用域中的變量的函數(shù),有興趣的可以看看幾篇文章,看完會又更深刻的理解

          破解前端面試(80% 應(yīng)聘者不及格系列):從閉包說起


          8、說一下你對call/apply/bind的理解

          call/apply/bind都是用來修改this指向的

          apply 和 call 的區(qū)別
          apply 和 call 的區(qū)別是 call 方法接受的是若干個參數(shù)列表,而 apply 接收的是一個包含多個參數(shù)的數(shù)組(方便記憶:call有兩個l,表示可以傳遞多個參數(shù))

          bind 和 apply、call 區(qū)別
          call、apply都是直接調(diào)用,bind生成的this指向改變函數(shù)需要手動調(diào)用

          9、說一下你對原型、原型鏈的理解

          JavaScript深入之從原型到原型鏈


          10、js實現(xiàn)繼承的幾種方法

          比較常見的幾種:

          • 原型鏈繼承
          • 借用構(gòu)造函數(shù)繼承
          • 組合繼承
          • 原型式繼承
          • 寄生式繼承
          • 寄生組合式繼承 一般只建議寄生組合式繼承,因為其它方式的繼承會在一次實例中調(diào)用兩次父類的構(gòu)造函數(shù)或有其它缺點,代碼如下:
          js復(fù)制代碼function Parent(name) {
              this.name=name;
          }
          Parent.prototype.sayName=function() {
              console.log('parent name:', this.name);
          }
          function Child(name, parentName) {
              Parent.call(this, parentName);  
              this.name=name;    
          }
          function create(proto) {
              function F(){}
              F.prototype=proto;
              return new F();
          }
          Child.prototype=create(Parent.prototype);
          Child.prototype.sayName=function() {
              console.log('child name:', this.name);
          }
          Child.prototype.constructor=Child;
          
          var parent=new Parent('father');
          parent.sayName();    // parent name: father
          
          var child=new Child('son', 'father');
          

          其他幾種繼承方式,可參考:JavaScript常用八種繼承方案


          11、深淺拷貝

          深拷貝: JSON.parse(JSON.stringify(data)) 遞歸

          淺拷貝: Object.assign() 擴(kuò)展運算符(...) Array.prototype.concat() Array.prototype.slice()

          12、事件循環(huán)機(jī)制/Event Loop

          說說事件循環(huán)機(jī)制(滿分答案來了)


          13、防抖與節(jié)流

          防抖: 防抖就是將一段時間內(nèi)連續(xù)的多次觸發(fā)轉(zhuǎn)化為一次觸發(fā)。一般可以使用在用戶輸入停止一段時間過后再去獲取數(shù)據(jù),而不是每次輸入都去獲取
          防抖應(yīng)用場景:

          • 保存、跳轉(zhuǎn)、登錄等按鈕的頻繁點擊
          • 搜索框搜索


          節(jié)流: 節(jié)流,顧名思義,控制流量。用于用戶在與頁面交互時控制事件發(fā)生的頻率,一般場景是單位的時間或其它間隔內(nèi)定時執(zhí)行操作。一段時間內(nèi),事件在每次到達(dá)我們規(guī)定的間隔 n 秒時觸發(fā)一次
          節(jié)流應(yīng)用場景:

          • scroll,resize, touchmove, mousemove等極易持續(xù)性促發(fā)事件的相關(guān)動畫問題,降低頻率
          • 瀏覽器播放事件


          14、函數(shù)柯里化

          在計算機(jī)科學(xué)中,柯里化(Currying)是把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù),并且返回接受余下的參數(shù)且返回結(jié)果的新函數(shù)的技術(shù)。

          js復(fù)制代碼function curry(fn, args) {
              var length=fn.length;
              var args=args || [];
              return function(){
                  newArgs=args.concat(Array.prototype.slice.call(arguments));
                  if (newArgs.length < length) {
                      return curry.call(this,fn,newArgs);
                  } else {
                      return fn.apply(this,newArgs);
                  }
              }
          }
          
          function multiFn(a, b, c) {
              return a * b * c;
          }
          
          var multi=curry(multiFn);
          
          multi(2)(3)(4);
          multi(2,3,4);
          multi(2)(3,4);
          multi(2,3)(4);
          


          15、手寫代碼

          這里面包含了大部分的常見手寫代碼: JavaScript手寫代碼無敵秘籍



          三、ES6

          1、常用的es6語法有哪些

          • let、const
          • 解構(gòu)賦值
          • 模板字符串
          • 箭頭函數(shù)
          • 函數(shù)默認(rèn)值
          • promise
          • set、map結(jié)構(gòu)
          • class類
          • symbol
          • Iterator 和 for...of 循環(huán).
          • 數(shù)值的擴(kuò)展方法
          • 數(shù)組的擴(kuò)展方法
          • 正則的擴(kuò)展方法
          • 對象的擴(kuò)展方法


          2、說下var、let、const的區(qū)別

          • let、const不存在變量提升,var存在變量提升
          • 在嚴(yán)格模式下let、const不能重復(fù)聲明,var可以重復(fù)聲明
          • let、const有塊級作用域,var沒有塊級作用域
          • const聲明一個只讀的常量。一旦聲明,常量的值就不能改變

          注: const實際上保證的,并不是變量的值不得改動,而是變量指向的那個內(nèi)存地址所保存的數(shù)據(jù)不得改動。對于簡單類型的數(shù)據(jù)(數(shù)值、字符串、布爾值),值就保存在變量指向的那個內(nèi)存地址,因此等同于常量。但對于復(fù)合類型的數(shù)據(jù)(主要是對象和數(shù)組),變量指向的內(nèi)存地址,保存的只是一個指向?qū)嶋H數(shù)據(jù)的指針,const只能保證這個指針是固定的(即總是指向另一個固定的地址),至于它指向的數(shù)據(jù)結(jié)構(gòu)是不是可變的,就完全不能控制了。因此,將一個對象聲明為常量必須非常小心。


          3、說說你對promise的了解

          promise是異步編程的一種解決方案。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息

          詳細(xì)的可以參考:要就來45道Promise面試題一次爽到底


          4、setTimeout、Promise、Async/Await 的區(qū)別

          • 其中setTimeout的回調(diào)函數(shù)放到宏任務(wù)隊列里,等到執(zhí)行棧清空以后執(zhí)行
          • promise.then里的回調(diào)函數(shù)會放到相應(yīng)宏任務(wù)的微任務(wù)隊列里,等宏任務(wù)里面的同步代碼執(zhí)行完再執(zhí)行
          • async函數(shù)表示函數(shù)里面可能會有異步方法,await后面跟一個表達(dá)式,async方法執(zhí)行時,遇到await會立即執(zhí)行表達(dá)式,然后把表達(dá)式后面的代碼放到微任務(wù)隊列里,讓出執(zhí)行棧讓同步代碼先執(zhí)行

          5、class類的理解

          類定義
          與函數(shù)類型相似,定義類也有兩種主要方式:類聲明和類表達(dá)式。這兩種方式都使用 class 關(guān)鍵 字加大括號:

          js復(fù)制代碼class Person {} // 類聲明
          const Animal=class {}; // 類表達(dá)式
          

          與函數(shù)表達(dá)式類似,類表達(dá)式在它們被求值前也不能引用。不過,與函數(shù)定義不同的是,雖然函數(shù) 聲明可以提升,但類定義不能:

          js復(fù)制代碼console.log(FunctionExpression); // undefined 
          var FunctionExpression=function() {}; 
          console.log(FunctionExpression); // function() {} 
           
          console.log(FunctionDeclaration); // FunctionDeclaration() {} 
          function FunctionDeclaration() {} 
          console.log(FunctionDeclaration); // FunctionDeclaration() {} 
           
          console.log(ClassExpression); // undefined 
          var ClassExpression=class {}; 
          console.log(ClassExpression); // class {} 
           
          console.log(ClassDeclaration); // ReferenceError: ClassDeclaration is not defined 
          class ClassDeclaration {} 
          console.log(ClassDeclaration); // class ClassDeclaration {} 
          

          類構(gòu)成
          類可以包含構(gòu)造函數(shù)方法、實例方法、獲取函數(shù)、設(shè)置函數(shù)和靜態(tài)類方法,但這些都不是必需的。 空的類定義照樣有效。默認(rèn)情況下,類定義中的代碼都在嚴(yán)格模式下執(zhí)行

          構(gòu)造函數(shù) constructor
          constructor()方法是類的默認(rèn)方法,通過new命令生成對象實例時,自動調(diào)用該方法。一個類必須有constructor()方法,如果沒有顯式定義,一個空的constructor()方法會被默認(rèn)添加。

          類的實例化
          class 的實例化必須通過 new 關(guān)鍵字

          js復(fù)制代碼class Example {} 
          let exam1=Example(); 
          // Class constructor Example cannot be invoked without 'new'
          

          使用 new 調(diào)用類的構(gòu)造函數(shù)會執(zhí)行如下操作。
          (1) 在內(nèi)存中創(chuàng)建一個新對象。
          (2) 這個新對象內(nèi)部的[[Prototype]]指針被賦值為構(gòu)造函數(shù)的 prototype 屬性。
          (3) 構(gòu)造函數(shù)內(nèi)部的 this 被賦值為這個新對象(即 this 指向新對象)
          (4) 執(zhí)行構(gòu)造函數(shù)內(nèi)部的代碼(給新對象添加屬性)。
          (5) 如果構(gòu)造函數(shù)返回非空對象,則返回該對象;否則,返回剛創(chuàng)建的新對象。

          類的所有實例共享一個原型對象

          js復(fù)制代碼class Example {
              constructor(a, b) {
                  this.a=a;
                  this.b=b;
                  console.log('Example');
              }
              sum() {
                  return this.a + this.b;
              }
          }
          let exam1=new Example(2, 1);
          let exam2=new Example(3, 1);
          console.log(exam1._proto_==exam2._proto_); // true 
          
          exam1._proto_.sub=function () {
              return this.a - this.b;
          }
          console.log(exam1.sub()); // 1 
          console.log(exam2.sub()); // 2
          

          上面代碼中,exam1和exam2都是Example的實例,它們的原型都是Example.prototype,所以__proto__屬性是相等的

          setter、getter
          在“類”的內(nèi)部可以使用get和set關(guān)鍵字,對某個屬性設(shè)置存值函數(shù)和取值函數(shù),攔截該屬性的存取行為。

          靜態(tài)方法 static
          類(class)通過 static 關(guān)鍵字定義靜態(tài)方法。不能在類的實例上調(diào)用靜態(tài)方法,而應(yīng)該通過類本身調(diào)用。這些通常是實用程序方法,例如創(chuàng)建或克隆對象的功能。
          類相當(dāng)于實例的原型,所有在類中定義的方法,都會被實例繼承。如果在一個方法前,加上static關(guān)鍵字,就表示該方法不會被實例繼承,而是直接通過類來調(diào)用,這就稱為“靜態(tài)方法”。

          js復(fù)制代碼class Foo {
              static classMethod() {
                  return 'hello';
              }
          }
          
          Foo.classMethod() // 'hello'
          
          var foo=new Foo();
          foo.classMethod()
          // TypeError: foo.classMethod is not a function
          

          上面代碼中,F(xiàn)oo類的classMethod方法前有static關(guān)鍵字,表明該方法是一個靜態(tài)方法,可以直接在Foo類上調(diào)用(Foo.classMethod()),而不是在Foo類的實例上調(diào)用。如果在實例上調(diào)用靜態(tài)方法,會拋出一個錯誤,表示不存在該方法。

          關(guān)鍵字 super
          super關(guān)鍵字用于訪問和調(diào)用一個對象的父對象上的函數(shù)。

          繼承 extends
          ES6 類支持單繼承。使用 extends 關(guān)鍵字,就可以繼承任何擁有[[Construct]]和原型的對象。 很大程度上,這意味著不僅可以繼承一個類,也可以繼承普通的構(gòu)造函數(shù)(保持向后兼容):

          js復(fù)制代碼class Vehicle {} 
           
          // 繼承類 
          class Bus extends Vehicle {} 
           
          let b=new Bus(); 
          console.log(b instanceof Bus); // true 
          console.log(b instanceof Vehicle); // true 
           
           
          function Person() {} 
           
          // 繼承普通構(gòu)造函數(shù) 
          class Engineer extends Person {} 
           
          let e=new Engineer(); 
          console.log(e instanceof Engineer); // true 
          console.log(e instanceof Person); // true 
          



          四、瀏覽器、網(wǎng)絡(luò)基礎(chǔ)

          1、如何用js去實現(xiàn)一個ajax

          大概步驟如下,具體要針對具體業(yè)務(wù)封裝:

          js復(fù)制代碼// 創(chuàng)建 XMLHttpRequest 對象
          var ajax=new XMLHttpRequest();
          // 規(guī)定請求的類型、URL 以及是否異步處理請求。
          ajax.open('GET', url);
          // 發(fā)送信息至服務(wù)器時內(nèi)容編碼類型
          ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
          // 發(fā)送請求
          ajax.send(null);  
          // 接受服務(wù)器響應(yīng)數(shù)據(jù)
          ajax.onreadystatechange=function () {
              if (obj.readyState==4 && (obj.status==200 || obj.status==304)) { 
              }
          };
          


          2、常見的http狀態(tài)碼

          狀態(tài)碼

          含義

          200

          表示從客戶端發(fā)來的請求在服務(wù)器端被正常處理了

          204

          無內(nèi)容。服務(wù)器成功處理,但未返回內(nèi)容。在未更新網(wǎng)頁的情況下,可確保瀏覽器繼續(xù)顯示當(dāng)前文檔

          301

          永久移動。請求的資源已被永久的移動到新URI,返回信息會包括新的URI,瀏覽器會自動定向到新URI。今后任何新的請求都應(yīng)使用新的URI代替

          302

          臨時移動。與301類似。但資源只是臨時被移動。客戶端應(yīng)繼續(xù)使用原有URI

          304

          未修改。所請求的資源未修改,服務(wù)器返回此狀態(tài)碼時,不會返回任何資源。
          客戶端通常會緩存訪問過的資源,通過提供一個頭信息指出客戶端希望只返回在指定日期之后修改的資源

          400

          表示請求報文中存在語法錯誤。當(dāng)錯誤發(fā)生時,需修改請求的內(nèi)容后再次發(fā)送請求

          401

          表示未授權(quán)(Unauthorized),當(dāng)前請求需要用戶驗證

          403

          表示對請求資源的訪問被服務(wù)器拒絕了

          404

          表示服務(wù)器上無法找到請求的資源。除此之外,也可以在服務(wù)器端拒絕請求且不想說明理由時使用

          500

          表示服務(wù)器端在執(zhí)行請求時發(fā)生了錯誤。也有可能是Web應(yīng)用存在的bug或某些臨時的故障

          502

          作為網(wǎng)關(guān)或者代理工作的服務(wù)器嘗試執(zhí)行請求時,從遠(yuǎn)程服務(wù)器接收到了一個無效的響應(yīng)

          503

          表示服務(wù)器暫時處于超負(fù)載或正在進(jìn)行停機(jī)維護(hù),現(xiàn)在無法處理請求

          504

          網(wǎng)關(guān)超時, 服務(wù)器作為網(wǎng)關(guān)或代理,但是沒有及時從上游服務(wù)器收到請求

          3、ajax的請求頭和響應(yīng)頭包含哪些東西

          Request header

          解釋

          Accept

          指定客戶端能夠接收的內(nèi)容類型,如:application/json, text/plain

          Accept-Encoding

          指定瀏覽器可以支持的web服務(wù)器返回內(nèi)容壓縮編碼類型,如:gzip, deflate, br

          Accept-Language

          瀏覽器所希望的語言種類

          Cache-Control

          緩存機(jī)制,默認(rèn)no-cache

          Connec-Length

          請求頭的長度

          Content-Type

          發(fā)送的數(shù)據(jù)類型, 如:application/x-www-form-urlencoded,
          application/json,multipart/form-data(可用來做文件上傳),

          Connection

          表示是否需要持久連接。(HTTP 1.1默認(rèn)進(jìn)行持久連接)

          Cookie

          HTTP請求發(fā)送時,會把保存在該請求域名下的所有cookie值一起發(fā)送給web服務(wù)器

          Host

          指定請求的服務(wù)器的域名和端口號

          If-Modified-Since

          只有當(dāng)所請求的內(nèi)容在指定的日期之后又經(jīng)過修改才返回它,否則返回304“Not Modified”應(yīng)答

          Referer

          包含一個URL,用戶從該URL代表的頁面出發(fā)訪問當(dāng)前請求的頁面

          User-Agent

          瀏覽器信息,如果Servlet返回的內(nèi)容與瀏覽器類型有關(guān)則該值非常有用

          Cookie

          這是最重要的請求頭信息之一


          Response header

          解釋

          Allow

          服務(wù)器支持哪些請求方法(如GET、POST等)

          Content-Encoding

          文檔的編碼(Encode)方法。
          只有在解碼之后才可以得到Content-Type頭指定的內(nèi)容類型。
          利用gzip壓縮文檔能夠顯著地減少HTML文檔的下載時間。
          Java的GZIPOutputStream可以很方便地進(jìn)行g(shù)zip壓縮,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。
          因此,Servlet應(yīng)該通過查看Accept-Encoding頭(即request.getHeader("Accept-Encoding"))檢查瀏覽器是否支持gzip,
          為支持gzip的瀏覽器返回經(jīng)gzip壓縮的HTML頁面,為其他瀏覽器返回普通頁面

          Content-Length

          表示內(nèi)容長度。
          只有當(dāng)瀏覽器使用持久HTTP連接時才需要這個數(shù)據(jù)。
          如果你想要利用持久連接的優(yōu)勢,可以把輸出文檔寫入 ByteArrayOutputStream,
          完成后查看其大小,然后把該值放入Content-Length頭,
          最后通過byteArrayStream.writeTo發(fā)送內(nèi)容

          Content-Type

          表示后面的文檔屬于什么MIME類型。
          Servlet默認(rèn)為text/plain,但通常需要顯式地指定為text/html。
          由于經(jīng)常要設(shè)置Content-Type,因此HttpServletResponse提供了一個專用的方法setContentType

          Date

          當(dāng)前的GMT時間。你可以用setDateHeader來設(shè)置這個頭以避免轉(zhuǎn)換時間格式的麻煩

          Expires

          應(yīng)該在什么時候認(rèn)為文檔已經(jīng)過期,從而不再緩存它?

          Last-Modified

          文檔的最后改動時間。客戶可以通過If-Modified-Since請求頭提供一個日期,
          該請求將被視為一個條件GET,只有改動時間遲于指定時間的文檔才會返回,
          否則返回一個304(Not Modified)狀態(tài)。Last-Modified也可用setDateHeader方法來設(shè)置。

          Location

          表示客戶應(yīng)當(dāng)?shù)侥睦锶ヌ崛∥臋n。Location通常不是直接設(shè)置的,而是通過HttpServletResponse的sendRedirect方法,該方法同時設(shè)置狀態(tài)代碼為302

          Refresh

          表示瀏覽器應(yīng)該在多少時間之后刷新文檔,以秒計

          Server

          服務(wù)器名字。Servlet一般不設(shè)置這個值,而是由Web服務(wù)器自己設(shè)置

          Set-Cookie

          設(shè)置和頁面關(guān)聯(lián)的Cookie。Servlet不應(yīng)使用response.setHeader("Set-Cookie", ...),而是應(yīng)使用HttpServletResponse提供的專用方法addCookie

          WWW-Authenticate

          客戶應(yīng)該在Authorization頭中提供什么類型的授權(quán)信息?
          在包含401(Unauthorized)狀態(tài)行的應(yīng)答中這個頭是必需的

          4、為什么會產(chǎn)生跨域?怎么去解決跨域問題?

          跨域是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實施的安全限制。瀏覽器從一個域名的網(wǎng)頁去請求另一個域名的資源時,出現(xiàn)域名、端口、協(xié)議任一不同,都屬于跨域。

          跨域解決方案:

          • 通過jsonp跨域
          • 跨域資源共享(CORS)
          • nginx代理跨域
          • nodejs中間件代理跨域
          • WebSocket協(xié)議跨域
          • postMessage跨域
          • document.domain + iframe跨域
          • location.hash + iframe
          • window.name + iframe跨域

          詳情見:九種跨域方式實現(xiàn)原理(完整版)


          5、post的預(yù)請求了解過嗎?

          預(yù)請求就是復(fù)雜請求(可能對服務(wù)器數(shù)據(jù)產(chǎn)生副作用的HTTP請求方法,如put,delete都會對服務(wù)器數(shù)據(jù)進(jìn)行更修改,所以要先詢問服務(wù)器)。
          跨域請求中,瀏覽器自發(fā)的發(fā)起的預(yù)請求,瀏覽器會查詢到兩次請求,第一次的請求參數(shù)是options,以檢測試實際請求是否可以被瀏覽器接受

          什么情況下發(fā)生

          • 請求方法不是get head post
          • post 的content-type不是application/x-www-form-urlencode,multipart/form-data,text/plain ([也就是把content-type設(shè)置成"application/json"])
          • 請求設(shè)置了自定義的header字段: 比如業(yè)務(wù)需求,傳一個字段,方便后端獲取,不需要每個接口都傳

          例如設(shè)置了post請求的content-type:application/json,就會發(fā)生預(yù)請求


          6、從輸入URL到頁面展示,這中間發(fā)生了什么?

          • DNS 解析:將域名解析成 IP 地址
          • TCP 連接:TCP 三次握手
          • 發(fā)送 HTTP 請求
          • 服務(wù)器處理請求并返回 HTTP 報文
          • 瀏覽器解析渲染頁面
          • 斷開連接:TCP 四次揮手

          詳細(xì)可以參考: 從輸入URL開始建立前端知識體系


          7、說一下tcp三次握手和四次揮手

          三次握手
          第一次握手:客戶端給服務(wù)端發(fā)一個 SYN 報文,并指明客戶端的初始化序列號 ISN(c)。此時客戶端處于 SYN_SEND 狀態(tài)。
          第二次握手:服務(wù)器收到客戶端的 SYN 報文之后,會以自己的 SYN 報文作為應(yīng)答,并且也是指定了自己的初始化序列號 ISN(s)。同時會把客戶端的 ISN + 1 作為ACK 的值,表示自己已經(jīng)收到了客戶端的 SYN,此時服務(wù)器處于 SYN_RCVD 的狀態(tài)。
          第三次握手:客戶端收到 SYN 報文之后,會發(fā)送一個 ACK 報文,當(dāng)然,也是一樣把服務(wù)器的 ISN + 1 作為 ACK 的值,表示已經(jīng)收到了服務(wù)端的 SYN 報文,此時客戶端處于 ESTABLISHED 狀態(tài)。服務(wù)器收到 ACK 報文之后,也處于 ESTABLISHED 狀態(tài),此時,雙方已建立起了連接

          四次揮手
          第一次揮手:客戶端先發(fā)送FIN報文(第24幀),用來關(guān)閉主動方到被動關(guān)閉方的數(shù)據(jù)傳送,也就是客戶端告訴服務(wù)器:我已經(jīng)不會再給你發(fā)數(shù)據(jù)了(當(dāng)然,在fin包之前發(fā)送出去的數(shù)據(jù),如果沒有收到對應(yīng)的ack確認(rèn)報文,客戶端依然會重發(fā)這些數(shù)據(jù)),但此時客戶端還可以接受數(shù)據(jù)。
          第二次揮手:Server端接到FIN報文后,如果還有數(shù)據(jù)沒有發(fā)送完成,則不必急著關(guān)閉Socket,可以繼續(xù)發(fā)送數(shù)據(jù)。所以服務(wù)器端先發(fā)送ACK(第25幀),告訴Client端:請求已經(jīng)收到了,但是我還沒準(zhǔn)備好,請繼續(xù)等待停止的消息。這個時候Client端就進(jìn)入FIN_WAIT狀態(tài),繼續(xù)等待Server端的FIN報文。
          第三次揮手:當(dāng)Server端確定數(shù)據(jù)已發(fā)送完成,則向Client端發(fā)送FIN報文(第26幀),告訴Client端:服務(wù)器這邊數(shù)據(jù)發(fā)完了,準(zhǔn)備好關(guān)閉連接了。
          第四次揮手:Client端收到FIN報文后,就知道可以關(guān)閉連接了,但是他還是不相信網(wǎng)絡(luò),所以發(fā)送ACK后進(jìn)入TIME_WAIT狀態(tài)(第27幀), Server端收到ACK后,就知道可以斷開連接了。Client端等待了2MSL后依然沒有收到回復(fù),則證明Server端已正常關(guān)閉,最后,Client端也可以關(guān)閉連接了至此,TCP連接就已經(jīng)完全關(guān)閉了!

          為了方便記憶,整理個白話文版本,以找工作和離職舉例(客戶端=小明,服務(wù)端=人事)

          第一次握手:由小明發(fā)起,小明向招聘人事發(fā)送了一份簡歷,里面包含了小明的個人基本信息
          第二次握手:由人事發(fā)起,人事收到小明的簡歷后,安排面試,面試通過后,發(fā)送了一份offer給小明
          第三次握手:由小明發(fā)起,小明收到offer后,會發(fā)送一個確認(rèn)offer的回復(fù),表示已經(jīng)收到offer

          第一次揮手:由小明發(fā)起,告訴服務(wù)器我要離職跑路了
          第二次揮手:由人事發(fā)起,告訴小明我知道你要離職了,但是你先把工作交接好
          第三次揮手:由人事發(fā)起,我看你的交接流程都走完了,你可以走人了
          第四次揮手:由小明發(fā)起,收到人事通知離職流程已經(jīng)走完了,告訴人事我明白就不來了,人事收到消息把此人從公司注銷


          8、說一下瀏覽器緩存策略

          大概流程如下:

          1. 第一次請求,無緩存,直接向服務(wù)器發(fā)請求,并將請求結(jié)果存入緩存中
          2. 第二次請求,在強(qiáng)制緩存時間內(nèi),緩存未過期,瀏覽器接使用緩存作為結(jié)果返回 200
          3. 第三次請求,強(qiáng)制緩存時間已過期,進(jìn)入?yún)f(xié)商緩存,向服務(wù)器請求,通過在Header中攜帶 If-Modified-Since(對應(yīng)瀏覽器返回的last-Modify) 或If-None-Match(對應(yīng)瀏覽器返回的Etag) 校驗緩存內(nèi)容是否有更新,Etag優(yōu)先級更高
          4. 緩存資源沒有更新,返回 304,瀏覽器繼續(xù)使用緩存,更新強(qiáng)制緩存時間
            緩存資源有更新,緩存失效,返回 200,重新返回資源和緩存標(biāo)識,再存入瀏覽器緩存中


          9、能不能說一說瀏覽器的本地存儲?

          瀏覽器的本地存儲主要分為Cookie、WebStorage和IndexedDB, 其中WebStorage又可以分為localStorage和sessionStorage。接下來我們就來一一分析這些本地存儲方案。

          Cookie
          HTTP Cookie,通常叫做Cookie,一開始是在客戶端用于存儲會話信息的。

          Cookie主要構(gòu)成

          • name:名稱,一個唯一確定的cookie的名稱,cookie的名稱必須經(jīng)過URL編碼。
          • value:值,存儲在cookie中的字符串值。值必須被URL編碼。
          • Domain:域,指明cookie對哪個域有效,所有向該域發(fā)送的請求都會包含這個信息。
          • path:路徑,對于指定域中的那個路徑,應(yīng)該向服務(wù)器發(fā)送cookie。
          • Expires/Max-Age:有效期,表示cookie的有效期。
          • HttpOnly:如果這個這個值設(shè)置為true,就不能通過JS腳本獲取cookie的值。通過這個值可以有效防止XSS攻擊。
          • Secure:安全標(biāo)志,指定后,cookie只有在使用SSL連接的時候才能發(fā)送到服務(wù)器。

          Cookie的原理

          第一次訪問網(wǎng)站時,瀏覽器發(fā)出請求,服務(wù)器響應(yīng)請求后,會在響應(yīng)頭中添加一個Set-Cookie,將cookie放入響應(yīng)請求中。

          在第二次發(fā)起請求時,瀏覽器通過Cookie請求頭部將cookie信息送給服務(wù)器,服務(wù)端根據(jù)cookie信息辨別用戶身份。

          Cookie的過期時間、域、路徑、有效期、適用站點都可以根據(jù)需要來指定。

          Cookie的生成

          Cookie的生成方式主要有兩種:

          • 服務(wù)端設(shè)置Cookie
          • 客戶端設(shè)置Cookie

          服務(wù)端設(shè)置方式參考上面Cookie的原理,具體的實現(xiàn)方式自行查閱相關(guān)資料。客戶端設(shè)置Cookie方法如下:

          js復(fù)制代碼document.cookie="name=zhangsan; age=20"
          

          Cookie的缺點

          • 每個特定域名下的cookie數(shù)量有限,不同瀏覽器數(shù)量限制不同。如果超過數(shù)量限制后再設(shè)置Cookie,瀏覽器就會清除以前設(shè)置的Cookie。
          • 大小只有4kb。
          • 每次HTTP請求都會默認(rèn)帶上Cookie,影響獲取資源的效率。
          • Cookie的獲取、設(shè)置、刪除方法需要我們自己去封裝。

          Web Storage
          Web Storage分為localStorage和sessionStorage
          localStorage
          localStorage有以下幾個特點:

          • 保持的數(shù)據(jù)永久有效,除非手動刪除;
          • 大小為5M
          • 僅在客戶端使用,不和服務(wù)端進(jìn)行通信
          • 接口封裝較好

          使用方法:

          js復(fù)制代碼// 設(shè)置
          localStorage.setItem('name', '張三')
          localStorage.age='25'
          // 取值
          localStorage.getItem('name')
          let age=localStorage.age
          // 移除
          localStorage.removeItem('name')
          // 移除所有
          localStorage.clear()
          

          sessionStorage
          sessionStorage對象存儲特定于某個會話的數(shù)據(jù),當(dāng)這個會話的頁簽或瀏覽器關(guān)閉,sessionStorage也就消失了。
          頁面刷新之后,存儲在sessionStorage中的數(shù)據(jù)仍然存在可用。
          sessionStorage的特點:

          • 會話級別的瀏覽器存儲
          • 大小為5M
          • 僅在客戶端使用,不和服務(wù)端通信
          • 接口封裝較好

          使用方法:

          js復(fù)制代碼// 設(shè)置
          sessionStorage.setItem('name', '張三')
          sessionStorage.age='25'
          // 取值
          sessionStorage.getItem('name')
          let age=sessionStorage.age
          // 移除
          sessionStorage.removeItem('name')
          // 移除所有
          sessionStorage.clear()
          

          sessionStorage和localStorage的區(qū)別:localStorage的數(shù)據(jù)可以長期保留,sessionStorage的數(shù)據(jù)在關(guān)閉頁面后即被清空

          IndexedDB
          IndexedDB,全稱Indexed Database API,是瀏覽器中保持結(jié)構(gòu)化數(shù)據(jù)的一種數(shù)據(jù)庫。
          IndexedDB的思想是創(chuàng)建一套API,方便保存和讀取JavaScript對象,同時支持查詢和搜索。

          IndexedDB特點

          • 鍵值對存儲:IndexedDB采用對象倉庫存儲數(shù)據(jù),可以存儲所有類型的數(shù)據(jù)。倉庫中數(shù)據(jù)以鍵值對的形式保持。
          • 異步:IndexedDB操作時不會鎖死瀏覽器,用戶依然可以進(jìn)行其他操作。
          • 支持事務(wù):有學(xué)過數(shù)據(jù)庫的對事務(wù)肯定不陌生。事務(wù)意味著在一系列操作中,只要有一步失敗,整個事務(wù)就都取消,數(shù)據(jù)庫回滾到事務(wù)執(zhí)行之前,不存在只改寫一部分?jǐn)?shù)據(jù)的情況。
          • 同源限制:IndexedDB受到同源限制,每一個數(shù)據(jù)庫對應(yīng)創(chuàng)建它的域名。網(wǎng)頁只能訪問自身域名下的數(shù)據(jù)庫,而不能訪問跨域的數(shù)據(jù)庫。
          • 儲存空間大: IndexedDB 的儲存空間比 localStorage大得多,一般來說不少于 250MB,甚至沒有上限。
          • 支持二進(jìn)制儲存: IndexedDB不僅可以儲存字符串,還可以儲存二進(jìn)制數(shù)據(jù)(ArrayBuffer 對象和 Blob 對象)。

          IndexedDB的入門教程,可以查看阮一峰老師的文章:瀏覽器數(shù)據(jù)庫 IndexedDB 入門教程

          總結(jié)

          • Cookie主要用于“維持狀態(tài)”,而非本地存儲數(shù)據(jù)
          • Web Storage是專門為瀏覽器提供的數(shù)據(jù)存儲機(jī)制,不與服務(wù)端發(fā)生通信
          • IndexedDB 用于客戶端存儲大量結(jié)構(gòu)化數(shù)據(jù)


          10、瀏覽器垃圾回收機(jī)制

          介紹
          瀏覽器的 Javascript 具有自動垃圾回收機(jī)制(GC:Garbage Collecation),也就是說,執(zhí)行環(huán)境會負(fù)責(zé)管理代碼執(zhí)行過程中使用的內(nèi)存。其原理是:垃圾收集器會定期(周期性)找出那些不在繼續(xù)使用的變量,然后釋放其內(nèi)存。但是這個過程不是實時的,因為其開銷比較大并且GC時停止響應(yīng)其他操作,所以垃圾回收器會按照固定的時間間隔周期性的執(zhí)行。

          不再使用的變量也就是生命周期結(jié)束的變量,當(dāng)然只可能是局部變量,全局變量的生命周期直至瀏覽器卸載頁面才會結(jié)束。局部變量只在函數(shù)的執(zhí)行過程中存在,而在這個過程中會為局部變量在棧或堆上分配相應(yīng)的空間,以存儲它們的值,然后在函數(shù)中使用這些變量,直至函數(shù)結(jié)束,而閉包中由于內(nèi)部函數(shù)的原因,外部函數(shù)并不能算是結(jié)束。

          還是上代碼說明吧:

          js復(fù)制代碼function fn1() {
              var obj={ name: 'hanzichi', age: 10 };
          }
          function fn2() {
              var obj={ name:'hanzichi', age: 10 };
              return obj;
          }
          
          var a=fn1();
          var b=fn2();
          

          我們來看代碼是如何執(zhí)行的。首先定義了兩個function,分別叫做fn1和fn2,當(dāng)fn1被調(diào)用時,進(jìn)入fn1的環(huán)境,會開辟一塊內(nèi)存存放對象{name: 'hanzichi', age: 10},而當(dāng)調(diào)用結(jié)束后,出了fn1的環(huán)境,那么該塊內(nèi)存會被js引擎中的垃圾回收器自動釋放;在fn2被調(diào)用的過程中,返回的對象被全局變量b所指向,所以該塊內(nèi)存并不會被釋放。

          這里問題就出現(xiàn)了:到底哪個變量是沒有用的?所以垃圾收集器必須跟蹤到底哪個變量沒用,對于不再有用的變量打上標(biāo)記,以備將來收回其內(nèi)存。用于標(biāo)記的無用變量的策略可能因?qū)崿F(xiàn)而有所區(qū)別,通常情況下有兩種實現(xiàn)方式:標(biāo)記清除和引用計數(shù)。引用計數(shù)不太常用,標(biāo)記清除較為常用。

          標(biāo)記清除
          js中最常用的垃圾回收方式就是標(biāo)記清除。當(dāng)變量進(jìn)入環(huán)境時,例如,在函數(shù)中聲明一個變量,就將這個變量標(biāo)記為“進(jìn)入環(huán)境”。從邏輯上講,永遠(yuǎn)不能釋放進(jìn)入環(huán)境的變量所占用的內(nèi)存,因為只要執(zhí)行流進(jìn)入相應(yīng)的環(huán)境,就可能會用到它們。而當(dāng)變量離開環(huán)境時,則將其標(biāo)記為“離開環(huán)境”。

          垃圾回收器在運行的時候會給存儲在內(nèi)存中的所有變量都加上標(biāo)記(當(dāng)然,可以使用任何標(biāo)記方式)。然后,它會去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標(biāo)記(閉包)。而在此之后再被加上標(biāo)記的變量將被視為準(zhǔn)備刪除的變量,原因是環(huán)境中的變量已經(jīng)無法訪問到這些變量了。最后,垃圾回收器完成內(nèi)存清除工作,銷毀那些帶標(biāo)記的值并回收它們所占用的內(nèi)存空間。 到目前為止,IE9+、Firefox、Opera、Chrome、Safari的js實現(xiàn)使用的都是標(biāo)記清除的垃圾回收策略或類似的策略,只不過垃圾收集的時間間隔互不相同。

          引用計數(shù)
          引用計數(shù)的含義是跟蹤記錄每個值被引用的次數(shù)。當(dāng)聲明了一個變量并將一個引用類型值賦給該變量時,則這個值的引用次數(shù)就是1。如果同一個值又被賦給另一個變量,則該值的引用次數(shù)加1。相反,如果包含對這個值引用的變量又取得了另外一個值,則這個值的引用次數(shù)減1。當(dāng)這個值的引用次數(shù)變成0時,則說明沒有辦法再訪問這個值了,因而就可以將其占用的內(nèi)存空間回收回來。這樣,當(dāng)垃圾回收器下次再運行時,它就會釋放那些引用次數(shù)為0的值所占用的內(nèi)存。

          js復(fù)制代碼function test() {
              var a={}; // a的引用次數(shù)為0 
              var b=a; // a的引用次數(shù)加1,為1 
              var c=a; // a的引用次數(shù)再加1,為2
              var b={}; // a的引用次數(shù)減1,為1
          }
          

          Netscape Navigator3是最早使用引用計數(shù)策略的瀏覽器,但很快它就遇到一個嚴(yán)重的問題:循環(huán)引用。循環(huán)引用指的是對象A中包含一個指向?qū)ο驜的指針,而對象B中也包含一個指向?qū)ο驛的引用。

          js復(fù)制代碼function fn() {
              var a={};
              var b={};
              a.pro=b;
              b.pro=a;
          }
          fn();
          

          以上代碼a和b的引用次數(shù)都是2,fn()執(zhí)行完畢后,兩個對象都已經(jīng)離開環(huán)境,在標(biāo)記清除方式下是沒有問題的,但是在引用計數(shù)策略下,因為a和b的引用次數(shù)不為0,所以不會被垃圾回收器回收內(nèi)存,如果fn函數(shù)被大量調(diào)用,就會造成內(nèi)存泄露。在IE7與IE8上,內(nèi)存直線上升。

          我們知道,IE中有一部分對象并不是原生js對象。例如,其內(nèi)存泄露DOM和BOM中的對象就是使用C++以COM對象的形式實現(xiàn)的,而COM對象的垃圾回收機(jī)制采用的就是引用計數(shù)策略。因此,即使IE的js引擎采用標(biāo)記清除策略來實現(xiàn),但js訪問的COM對象依然是基于引用計數(shù)策略的。換句話說,只要在IE中涉及COM對象,就會存在循環(huán)引用的問題。

          js復(fù)制代碼var element=document.getElementById("some_element");
          var myObject=new Object();
          myObject.e=element;
          element.o=myObject;
          

          這個例子在一個DOM元素(element)與一個原生js對象(myObject)之間創(chuàng)建了循環(huán)引用。其中,變量myObject有一個屬性e指向element對象;而變量element也有一個屬性o回指myObject。由于存在這個循環(huán)引用,即使例子中的DOM從頁面中移除,它也永遠(yuǎn)不會被回收。

          舉個栗子:

          js復(fù)制代碼myObject.element=null;
          element.o=null;
          
          window.onload=function outerFunction() {
              var obj=document.getElementById("element");
              obj.onclick=function innerFunction(){};
              obj=null;
          };
          

          這段代碼看起來沒什么問題,但是obj引用了document.getElementById('element'),而document.getElementById('element')的onclick方法會引用外部環(huán)境中的變量,自然也包括obj,是不是很隱蔽啊。(在比較新的瀏覽器中在移除Node的時候已經(jīng)會移除其上的event了,但是在老的瀏覽器,特別是ie上會有這個bug)

          解決辦法:

          最簡單的方式就是自己手工解除循環(huán)引用,比如剛才的函數(shù)可以這樣

          js復(fù)制代碼myObject.element=null;
          element.o=null;
          
          window.onload=function outerFunction(){
              var obj=document.getElementById("element");
              obj.onclick=function innerFunction(){};
              obj=null;
          };
          

          將變量設(shè)置為null意味著切斷變量與它此前引用的值之間的連接。當(dāng)垃圾回收器下次運行時,就會刪除這些值并回收它們占用的內(nèi)存。

          要注意的是,IE9+并不存在循環(huán)引用導(dǎo)致Dom內(nèi)存泄露問題,可能是微軟做了優(yōu)化,或者Dom的回收方式已經(jīng)改變

          11、談?wù)勀銓χ乩L和回流的理解

          在討論回流與重繪之前,我們要知道:

          1. 瀏覽器使用流式布局模型 (Flow Based Layout)。
          2. 瀏覽器會把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就產(chǎn)生了Render Tree。
          3. 有了RenderTree,我們就知道了所有節(jié)點的樣式,然后計算他們在頁面上的大小和位置,最后把節(jié)點繪制到頁面上。
          4. 由于瀏覽器使用流式布局,對Render Tree的計算通常只需要遍歷一次就可以完成,但table及其內(nèi)部元素除外,他們可能需要多次計算,通常要花3倍于同等元素的時間,這也是為什么要避免使用table布局的原因之一。

          一句話:回流必將引起重繪,重繪不一定會引起回流

          回流 (Reflow)

          當(dāng)Render Tree中部分或全部元素的尺寸、結(jié)構(gòu)、或某些屬性發(fā)生改變時,瀏覽器重新渲染部分或全部文檔的過程稱為回流。

          會導(dǎo)致回流的操作:

          • 頁面首次渲染
          • 瀏覽器窗口大小發(fā)生改變
          • 元素尺寸或位置發(fā)生改變
          • 元素內(nèi)容變化(文字?jǐn)?shù)量或圖片大小等等)
          • 元素字體大小變化
          • 添加或者刪除可見的DOM元素
          • 激活CSS偽類(例如::hover)
          • 查詢某些屬性或調(diào)用某些方法

          一些常用且會導(dǎo)致回流的屬性和方法:

          • clientWidth、clientHeight、clientTop、clientLeft
          • offsetWidth、offsetHeight、offsetTop、offsetLeft
          • scrollWidth、scrollHeight、scrollTop、scrollLeft
          • scrollIntoView()、scrollIntoViewIfNeeded()
          • getComputedStyle()
          • getBoundingClientRect()
          • scrollTo()

          重繪 (Repaint)

          當(dāng)頁面中元素樣式的改變并不影響它在文檔流中的位置時(例如:color、background-color、visibility等),瀏覽器會將新樣式賦予給元素并重新繪制它,這個過程稱為重繪。

          性能影響

          回流比重繪的代價要更高。

          有時即使僅僅回流一個單一的元素,它的父元素以及任何跟隨它的元素也會產(chǎn)生回流。

          現(xiàn)代瀏覽器會對頻繁的回流或重繪操作進(jìn)行優(yōu)化:

          瀏覽器會維護(hù)一個隊列,把所有引起回流和重繪的操作放入隊列中,如果隊列中的任務(wù)數(shù)量或者時間間隔達(dá)到一個閾值的,瀏覽器就會將隊列清空,進(jìn)行一次批處理,這樣可以把多次回流和重繪變成一次。

          當(dāng)你訪問以下屬性或方法時,瀏覽器會立刻清空隊列:

          • clientWidth、clientHeight、clientTop、clientLeft
          • offsetWidth、offsetHeight、offsetTop、offsetLeft
          • scrollWidth、scrollHeight、scrollTop、scrollLeft
          • width、height
          • getComputedStyle()
          • getBoundingClientRect()

          因為隊列中可能會有影響到這些屬性或方法返回值的操作,即使你希望獲取的信息與隊列中操作引發(fā)的改變無關(guān),瀏覽器也會強(qiáng)行清空隊列,確保你拿到的值是最精確的。

          如何避免

          CSS

          • 避免使用table布局。
          • 盡可能在DOM樹的最末端改變class。
          • 避免設(shè)置多層內(nèi)聯(lián)樣式。
          • 將動畫效果應(yīng)用到position屬性為absolute或fixed的元素上。
          • 避免使用CSS表達(dá)式(例如:calc())。

          JavaScript

          • 避免頻繁操作樣式,最好一次性重寫style屬性,或者將樣式列表定義為class并一次性更改class屬性。
          • 避免頻繁操作DOM,創(chuàng)建一個documentFragment,在它上面應(yīng)用所有DOM操作,最后再把它添加到文檔中。
          • 也可以先為元素設(shè)置display: none,操作結(jié)束后再把它顯示出來。因為在display屬性為none的元素上進(jìn)行的DOM操作不會引發(fā)回流和重繪。
          • 避免頻繁讀取會引發(fā)回流/重繪的屬性,如果確實需要多次使用,就用一個變量緩存起來。
          • 對具有復(fù)雜動畫的元素使用絕對定位,使它脫離文檔流,否則會引起父元素及后續(xù)元素頻繁回流。


          12、http和https的區(qū)別

          • HTTP是明文傳輸,不安全的,HTTPS是加密傳輸,安全的多
          • HTTP標(biāo)準(zhǔn)端口是80,HTTPS標(biāo)準(zhǔn)端口是443
          • HTTP不用認(rèn)證證書免費,HTTPS需要認(rèn)證證書要錢
          • 連接方式不同,HTTP三次握手,HTTPS中TLS1.2版本7次,TLS1.3版本6次
          • HTTP在OSI網(wǎng)絡(luò)模型中是在應(yīng)用層,而HTTPS的TLS是在傳輸層
          • HTTP是無狀態(tài)的,HTTPS是有狀態(tài)的


          13、HTTP2.0和HTTP1.X相比的新特性

          • 新的二進(jìn)制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本協(xié)議的格式解析存在天然缺陷,文本的表現(xiàn)形式有多樣性,要做到健壯性考慮的場景必然很多,二進(jìn)制則不同,只認(rèn)0和1的組合。基于這種考慮HTTP2.0的協(xié)議解析決定采用二進(jìn)制格式,實現(xiàn)方便且健壯。
          • 多路復(fù)用(MultiPlexing),即連接共享,即每一個request都是是用作連接共享機(jī)制的。一個request對應(yīng)一個id,這樣一個連接上可以有多個request,每個連接的request可以隨機(jī)的混雜在一起,接收方可以根據(jù)request的 id將request再歸屬到各自不同的服務(wù)端請求里面。
          • header壓縮,如上文中所言,對前面提到過HTTP1.x的header帶有大量信息,而且每次都要重復(fù)發(fā)送,HTTP2.0使用encoder來減少需要傳輸?shù)膆eader大小,通訊雙方各自cache一份header fields表,既避免了重復(fù)header的傳輸,又減小了需要傳輸?shù)拇笮 ?/li>
          • 服務(wù)端推送(server push),同SPDY一樣,HTTP2.0也具有server push功能


          14、DNS

          通俗易懂,了解什么是DNS及查詢過程


          15、CDN

          CDN是什么?使用CDN有什么優(yōu)勢?


          五、Vue

          最全的 Vue 面試題+詳解答案

          Vue.js 技術(shù)揭秘

          六、React

          高頻前端面試題匯總之React篇(上)

          高頻前端面試題匯總之React篇(下)

          搞懂這12個Hooks,保證讓你玩轉(zhuǎn)React

          React 源碼剖析系列 - 生命周期的管理藝術(shù)

          React Hooks 原理

          深入理解 React 高階組件

          七、性能優(yōu)化

          前端性能優(yōu)化手段從以下幾個方面入手:加載優(yōu)化、執(zhí)行優(yōu)化、渲染優(yōu)化、樣式優(yōu)化、腳本優(yōu)化

          加載優(yōu)化:減少HTTP請求、緩存資源、壓縮代碼、無阻塞、首屏加載、按需加載、預(yù)加載、壓縮圖像、減少Cookie、避免重定向、異步加載第三方資源

          執(zhí)行優(yōu)化:CSS寫在頭部,JS寫在尾部并異步、避免img、iframe等的src為空、盡量避免重置圖像大小、圖像盡量避免使用DataURL

          渲染優(yōu)化:設(shè)置viewport、減少DOM節(jié)點、優(yōu)化動畫、優(yōu)化高頻事件、GPU加速

          樣式優(yōu)化:避免在HTML中書寫style、避免CSS表達(dá)式、移除CSS空規(guī)則、正確使用display:display、不濫用float等

          腳本優(yōu)化:減少重繪和回流、緩存DOM選擇與計算、緩存.length的值、盡量使用事件代理、盡量使用id選擇器、touch事件優(yōu)化

          加載優(yōu)化

          1. 減少HTTP請求:盡量減少頁面的請求數(shù)(首次加載同時請求數(shù)不能超過4個),移動設(shè)備瀏覽器同時響應(yīng)請求為4個請求(Android支持4個,iOS5+支持6個)
          • 合并CSS和JS
          • 使用CSS精靈圖
          1. 緩存資源:使用緩存可減少向服務(wù)器的請求數(shù),節(jié)省加載時間,所有靜態(tài)資源都要在服務(wù)器端設(shè)置緩存,并且盡量使用長緩存(使用時間戳更新緩存)
          • 緩存一切可緩存的資源
          • 使用長緩存
          • 使用外聯(lián)的樣式和腳本
          1. 壓縮代碼:減少資源大小可加快網(wǎng)頁顯示速度,對代碼進(jìn)行壓縮,并在服務(wù)器端設(shè)置GZip
          • 壓縮代碼(多余的縮進(jìn)、空格和換行符)
          • 啟用Gzip
          1. 無阻塞:頭部內(nèi)聯(lián)的樣式和腳本會阻塞頁面的渲染,樣式放在頭部并使用link方式引入,腳本放在尾部并使用異步方式加載
          2. 首屏加載:首屏快速顯示可大大提升用戶對頁面速度的感知,應(yīng)盡量針對首屏的快速顯示做優(yōu)化
          3. 按需加載:將不影響首屏的資源和當(dāng)前屏幕不用的資源放到用戶需要時才加載,可大大提升顯示速度和降低總體流量(按需加載會導(dǎo)致大量重繪,影響渲染性能)
          • 懶加載
          • 滾屏加載
          • Media Query加載
          1. 預(yù)加載:大型資源頁面可使用Loading,資源加載完成后再顯示頁面,但加載時間過長,會造成用戶流失
          • 可感知Loading:進(jìn)入頁面時Loading
          • 不可感知Loading:提前加載下一頁
          1. 壓縮圖像:使用圖像時選擇最合適的格式和大小,然后使用工具壓縮,同時在代碼中用srcset來按需顯示( 過度壓縮圖像大小影響圖像顯示效果)
          • 使用TinyJpg和TinyPng壓縮圖像
          • 使用CSS3、SVG、IconFont代替圖像
          • 使用img的srcset按需加載圖像
          • 選擇合適的圖像:webp優(yōu)于jpg,png8優(yōu)于gif
          • 選擇合適的大小:首次加載不大于1014kb、不寬于640px
          • PS切圖時D端圖像保存質(zhì)量為80,M端圖像保存質(zhì)量為60
          1. 減少Cookie:Cookie會影響加載速度,靜態(tài)資源域名不使用Cookie
          2. 避免重定向:重定向會影響加載速度,在服務(wù)器正確設(shè)置避免重定向
          3. 異步加載第三方資源:第三方資源不可控會影響頁面的加載和顯示,要異步加載第三方資源

          執(zhí)行優(yōu)化

          1. CSS寫在頭部,JS寫在尾部并異步
          2. 避免img、iframe等的src為空:空src會重新加載當(dāng)前頁面,影響速度和效率
          3. 盡量避免重置圖像大小:多次重置圖像大小會引發(fā)圖像的多次重繪,影響性能
          4. 圖像盡量避免使用DataURL:DataURL圖像沒有使用圖像的壓縮算法,文件會變大,并且要解碼后再渲染,加載慢耗時長

          渲染優(yōu)化

          1. 設(shè)置viewport:HTML的viewport可加速頁面的渲染
          2. html復(fù)制代碼
          3. <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, minimum-scale=1, maximum-scale=1">
          4. 減少DOM節(jié)點:DOM節(jié)點太多影響頁面的渲染,盡量減少DOM節(jié)點
          5. 優(yōu)化動畫
          • 盡量使用CSS3動畫
          • 合理使用requestAnimationFrame動畫代替setTimeout
          • 適當(dāng)使用Canvas動畫:5個元素以內(nèi)使用CSS動畫,5個元素以上使用Canvas動畫,iOS8+可使用WebGL動畫
          1. 優(yōu)化高頻事件:scroll、touchmove等事件可導(dǎo)致多次渲染
          • 函數(shù)節(jié)流
          • 函數(shù)防抖
          • 使用requestAnimationFrame監(jiān)聽幀變化:使得在正確的時間進(jìn)行渲染
          • 增加響應(yīng)變化的時間間隔:減少重繪次數(shù)
          1. GPU加速:使用某些HTML5標(biāo)簽和CSS3屬性會觸發(fā)GPU渲染,請合理使用(過渡使用會引發(fā)手機(jī)耗電量增加) HTML標(biāo)簽:video、canvas、webgl CSS屬性:opacity、transform、transition

          樣式優(yōu)化

          1. 避免在HTML中書寫style
          2. 避免CSS表達(dá)式:CSS表達(dá)式的執(zhí)行需跳出CSS樹的渲染
          3. 移除CSS空規(guī)則:CSS空規(guī)則增加了css文件的大小,影響CSS樹的執(zhí)行
          4. 正確使用display:display會影響頁面的渲染
          • display:inline后不應(yīng)該再使用float、margin、padding、width和height
          • display:inline-block后不應(yīng)該再使用float
          • display:block后不應(yīng)該再使用vertical-align
          • display:table-*后不應(yīng)該再使用float和margin
          1. 不濫用float:float在渲染時計算量比較大,盡量減少使用
          2. 不濫用Web字體:Web字體需要下載、解析、重繪當(dāng)前頁面,盡量減少使用
          3. 不聲明過多的font-size:過多的font-size影響CSS樹的效率
          4. 值為0時不需要任何單位:為了瀏覽器的兼容性和性能,值為0時不要帶單位
          5. 標(biāo)準(zhǔn)化各種瀏覽器前綴
          6. 無前綴屬性應(yīng)放在最后
          7. CSS動畫屬性只用-webkit-、無前綴兩種
          8. 其它前綴為-webkit-、-moz-、-ms-、無前綴四種:Opera改用blink內(nèi)核,-o-已淘汰
          9. 避免讓選擇符看起來像正則表達(dá)式:高級選擇符執(zhí)行耗時長且不易讀懂,避免使用

          腳本優(yōu)化

          1. 減少重繪和回流
          • 避免不必要的DOM操作
          • 避免使用document.write
          • 減少drawImage
          • 盡量改變class而不是style,使用classList代替className
          1. 緩存DOM選擇與計算:每次DOM選擇都要計算和緩存
          2. 緩存.length的值:每次.length計算用一個變量保存值
          3. 盡量使用事件代理:避免批量綁定事件
          4. 盡量使用id選擇器:id選擇器選擇元素是最快的
          5. touch事件優(yōu)化:使用tap(touchstart和touchend)代替click(注意touch響應(yīng)過快,易引發(fā)誤操作)

          八、webpack

          Webpack面試題

          當(dāng)面試官問Webpack的時候他想知道什么


          九、TypeScript

          TypeScript免費視頻圖文教程(2W字)


          十、數(shù)據(jù)結(jié)構(gòu)與算法

          算法這塊呢,應(yīng)該是很多人頭疼的地方,沒有其他方法,只能去LeetCode老老實實刷題

          JavaScript 數(shù)據(jù)結(jié)構(gòu)與算法之美

          十一、前端安全

          1、說一說XSS攻擊

          就是攻擊者想盡一切辦法將可以執(zhí)行的代碼注入到網(wǎng)頁中, 主要分為以下幾種

          存儲型(server端)

          場景:見于帶有用戶保存數(shù)據(jù)的網(wǎng)站功能,如論壇發(fā)帖、商品評論、用戶私信等

          攻擊步驟:

          1. 攻擊者將惡意代碼提交到目標(biāo)網(wǎng)站的數(shù)據(jù)庫中
          2. 用戶打開目標(biāo)網(wǎng)站時,服務(wù)端將惡意代碼從數(shù)據(jù)庫中取出來,拼接在HTML中返回給瀏覽器
          3. 用戶瀏覽器在收到響應(yīng)后解析執(zhí)行,混在其中的惡意代碼也同時被執(zhí)行
          4. 惡意代碼竊取用戶數(shù)據(jù),并發(fā)送到指定攻擊者的網(wǎng)站,或者冒充用戶行為,調(diào)用目標(biāo)網(wǎng)站的接口,執(zhí)行惡意操作

          反射型(Server端)

          與存儲型的區(qū)別在于,存儲型的惡意代碼存儲在數(shù)據(jù)庫中,反射型的惡意代碼在URL上

          場景:通過 URL 傳遞參數(shù)的功能,如網(wǎng)站搜索、跳轉(zhuǎn)等

          攻擊步驟:

          1. 攻擊者構(gòu)造出特殊的 URL,其中包含惡意代碼
          2. 用戶打開帶有惡意代碼的 URL 時,網(wǎng)站服務(wù)端將惡意代碼從 URL 中取出,拼接在 HTML 中返回給瀏覽器
          3. 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,混在其中的惡意代碼也被執(zhí)行
          4. 惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站,或者冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作

          Dom 型(瀏覽器端)

          DOM 型 XSS 攻擊中,取出和執(zhí)行惡意代碼由瀏覽器端完成,屬于前端 JavaScript 自身的安全漏洞,而其他兩種 XSS 都屬于服務(wù)端的安全漏洞

          場景:通過 URL 傳遞參數(shù)的功能,如網(wǎng)站搜索、跳轉(zhuǎn)等

          攻擊步驟:

          1. ?攻擊者構(gòu)造出特殊的 URL,其中包含惡意代碼
          2. ?用戶打開帶有惡意代碼的 URL
          3. ?用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,前端 JavaScript 取出 URL 中的惡意代碼并執(zhí)行
          4. ?惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站,或者冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作

          預(yù)防方案:
          防止攻擊者提交惡意代碼,防止瀏覽器執(zhí)行惡意代碼

          1. 對數(shù)據(jù)進(jìn)行嚴(yán)格的輸出編碼:如HTML元素的編碼,JS編碼,CSS編碼,URL編碼等等; 避免拼接 HTML;Vue/React 技術(shù)棧,避免使用 v-html / dangerouslySetInnerHTML
          2. CSP HTTP Header,即 Content-Security-Policy、X-XSS-Protection
          • 增加攻擊難度,配置CSP(本質(zhì)是建立白名單,由瀏覽器進(jìn)行攔截)
          • Content-Security-Policy: default-src 'self'-所有內(nèi)容均來自站點的同一個源(不包括其子域名)
          • Content-Security-Policy: default-src 'self' *.trusted.com-允許內(nèi)容來自信任的域名及其子域名 (域名不必須與CSP設(shè)置所在的域名相同)
          • Content-Security-Policy: default-src yideng.com-該服務(wù)器僅允許通過HTTPS方式并僅從yideng.com域名來訪問文檔
          1. 輸入驗證:比如一些常見的數(shù)字、URL、電話號碼、郵箱地址等等做校驗判斷
          2. 開啟瀏覽器XSS防御:Http Only cookie,禁止 JavaScript 讀取某些敏感 Cookie,攻擊者完成 XSS 注入后也無法竊取此 Cookie
          3. 驗證碼

          2、說一說CSRF攻擊

          攻擊者誘導(dǎo)受害者進(jìn)入第三方網(wǎng)站,在第三方網(wǎng)站中,向被攻擊網(wǎng)站發(fā)送跨站請求。利用受害者在被攻擊網(wǎng)站已經(jīng)獲取的注冊憑證,繞過后臺的用戶驗證,達(dá)到冒充用戶對被攻擊的網(wǎng)站執(zhí)行某項操作的目的

          攻擊流程舉例

          1. ?受害者登錄 a.com,并保留了登錄憑證(Cookie)
          2. ?攻擊者引誘受害者訪問了b.com
          3. ?b.com 向 a.com 發(fā)送了一個請求:a.com/act=xx瀏覽器會默認(rèn)攜帶a.com的Cookie
          4. ?a.com接收到請求后,對請求進(jìn)行驗證,并確認(rèn)是受害者的憑證,誤以為是受害者自己發(fā)送的請求
          5. ?a.com以受害者的名義執(zhí)行了act=xx
          6. ?攻擊完成,攻擊者在受害者不知情的情況下,冒充受害者,讓a.com執(zhí)行了自己定義的操作

          攻擊類型

          1. ?GET型:如在頁面的某個 img 中發(fā)起一個 get 請求
          2. ?POST型:通過自動提交表單到惡意網(wǎng)站
          3. ?鏈接型:需要誘導(dǎo)用戶點擊鏈接

          預(yù)防方案:

          CSRF通常從第三方網(wǎng)站發(fā)起,被攻擊的網(wǎng)站無法防止攻擊發(fā)生,只能通過增強(qiáng)自己網(wǎng)站針對CSRF的防護(hù)能力來提升安全性。)

          1. 同源檢測:通過Header中的Origin Header 、Referer Header 確定,但不同瀏覽器可能會有不一樣的實現(xiàn),不能完全保證
          2. CSRF Token 校驗:將CSRF Token輸出到頁面中(通常保存在Session中),頁面提交的請求攜帶這個Token,服務(wù)器驗證Token是否
            正確
          3. 雙重cookie驗證:
            流程:
          4. 步驟1:在用戶訪問網(wǎng)站頁面時,向請求域名注入一個Cookie,內(nèi)容為隨機(jī)字符串(例如csrfcookie=v8g9e4ksfhw)
          5. 步驟2:在前端向后端發(fā)起請求時,取出Cookie,并添加到URL的參數(shù)中(接上例POST www.a.com/comment?csr…
          6. 步驟3:后端接口驗證Cookie中的字段與URL參數(shù)中的字段是否一致,不一致則拒絕
          7. 優(yōu)點:
          8. 無需使用Session,適用面更廣,易于實施
          9. Token儲存于客戶端中,不會給服務(wù)器帶來壓力
          10. 相對于Token,實施成本更低,可以在前后端統(tǒng)一攔截校驗,而不需要一個個接口和頁面添加
          11. 缺點:
          • Cookie中增加了額外的字段
          • 如果有其他漏洞(例如XSS),攻擊者可以注入Cookie,那么該防御方式失效
          • 難以做到子域名的隔離
          • 為了確保Cookie傳輸安全,采用這種防御方式的最好確保用整站HTTPS的方式,如果還沒切HTTPS的使用這種方式也會有風(fēng)險
          1. Samesite Cookie屬性:Google起草了一份草案來改進(jìn)HTTP協(xié)議,那就是為Set-Cookie響應(yīng)頭新增Samesite屬性,它用來標(biāo)明這個 Cookie是個“同站 Cookie”,同站Cookie只能作為第一方Cookie,不能作為第三方Cookie,Samesite 有兩個屬性值,Strict 為任何情況下都不可以作為第三方 Cookie ,Lax 為可以作為第三方 Cookie , 但必須是Get請求


          作者:前端老干部
          鏈接:https://juejin.cn/post/7127217262133510158

          、 介紹一下標(biāo)準(zhǔn)的CSS的盒子模型?與低版本IE的盒子模型有什么不同的?

          標(biāo)準(zhǔn)盒子模型:寬度=內(nèi)容的寬度(content)+ border + padding + margin

          低版本IE盒子模型:寬度=內(nèi)容寬度(content+border+padding)+ margin

          2、 box-sizing屬性?

          用來控制元素的盒子模型的解析模式,默認(rèn)為content-box

          context-box:W3C的標(biāo)準(zhǔn)盒子模型,設(shè)置元素的 height/width 屬性指的是content部分的高/寬

          border-box:IE傳統(tǒng)盒子模型。設(shè)置元素的height/width屬性指的是border + padding + content部分的高/寬

          3 、CSS選擇器有哪些?哪些屬性可以繼承?

          CSS選擇符:id選擇器(#myid)、類選擇器(.myclassname)、標(biāo)簽選擇器(div, h1, p)、相鄰選擇器(h1 + p)、子選擇器(ul > li)、后代選擇器(li a)、通配符選擇器(*)、屬性選擇器(a[rel="external"])、偽類選擇器(a:hover, li:nth-child)

          可繼承的屬性:font-size, font-family, color

          不可繼承的樣式:border, padding, margin, width, height

          優(yōu)先級(就近原則):!important > [ id > class > tag ]

          !important 比內(nèi)聯(lián)優(yōu)先級高

          4、 CSS優(yōu)先級算法如何計算?

          元素選擇符: 1

          class選擇符: 10

          id選擇符:100

          元素標(biāo)簽:1000

          1. !important聲明的樣式優(yōu)先級最高,如果沖突再進(jìn)行計算。
          2. 如果優(yōu)先級相同,則選擇最后出現(xiàn)的樣式。
          3. 繼承得到的樣式的優(yōu)先級最低。


          5、 CSS3新增偽類有那些?

          p:first-of-type 選擇屬于其父元素的首個元素

          p:last-of-type 選擇屬于其父元素的最后元素

          p:only-of-type 選擇屬于其父元素唯一的元素

          p:only-child 選擇屬于其父元素的唯一子元素

          p:nth-child(2) 選擇屬于其父元素的第二個子元素

          :enabled :disabled 表單控件的禁用狀態(tài)。

          :checked 單選框或復(fù)選框被選中。

          6 、如何居中div?如何居中一個浮動元素?如何讓絕對定位的div居中?

          div:

          border: 1px solid red;margin: 0 auto; 
          height: 50px;width: 80px;
          

          浮動元素的上下左右居中:

          border: 1px solid red;float: left;
          position: absolute;width: 200px;
          height: 100px;left: 50%;top: 50%;
          margin: -50px 0 0 -100px; 
          

          絕對定位的左右居中:

          border: 1px solid black;position: absolute;
          width: 200px;height: 100px;margin: 0 auto;
          left: 0;right: 0; 
          

          還有更加優(yōu)雅的居中方式就是用flexbox,我以后會做整理。

          7、 display有哪些值?說明他們的作用?

          inline(默認(rèn))--內(nèi)聯(lián)

          none--隱藏

          block--塊顯示

          table--表格顯示

          list-item--項目列表

          inline-block

          8、 position的值?

          static(默認(rèn)):按照正常文檔流進(jìn)行排列;

          relative(相對定位):不脫離文檔流,參考自身靜態(tài)位置通過 top, bottom, left, right 定位;

          absolute(絕對定位):參考距其最近一個不為static的父級元素通過top, bottom, left, right 定位;

          fixed(固定定位):所固定的參照對像是可視窗口。

          9、 CSS3有哪些新特性?

          1. RGBA和透明度
          2. background-image background-origin(content-box/padding-box/border-box) background-size background-repeat
          3. word-wrap(對長的不可分割單詞換行)word-wrap:break-word
          4. 文字陰影:text-shadow: 5px 5px 5px #FF0000;(水平陰影,垂直陰影,模糊距離,陰影顏色)
          5. font-face屬性:定義自己的字體
          6. 圓角(邊框半徑):border-radius 屬性用于創(chuàng)建圓角
          7. 邊框圖片:border-image: url(border.png) 30 30 round
          8. 盒陰影:box-shadow: 10px 10px 5px #888888
          9. 媒體查詢:定義兩套css,當(dāng)瀏覽器的尺寸變化時會采用不同的屬性


          10、 請解釋一下CSS3的flexbox(彈性盒布局模型),以及適用場景?

          該布局模型的目的是提供一種更加高效的方式來對容器中的條目進(jìn)行布局、對齊和分配空間。在傳統(tǒng)的布局方式中,block 布局是把塊在垂直方向從上到下依次排列的;而 inline 布局則是在水平方向來排列。彈性盒布局并沒有這樣內(nèi)在的方向限制,可以由開發(fā)人員自由操作。

          試用場景:彈性布局適合于移動前端開發(fā),在Android和ios上也完美支持。

          11、 用純CSS創(chuàng)建一個三角形的原理是什么?

          首先,需要把元素的寬度、高度設(shè)為0。然后設(shè)置邊框樣式。

          width: 0;height: 0;border-top: 40px solid transparent;
          border-left: 40px solid transparent;border-right: 40px solid transparent;
          border-bottom: 40px solid #ff0000;
          


          12、 一個滿屏品字布局如何設(shè)計?

          第一種真正的品字:

          1. 三塊高寬是確定的;
          2. 上面那塊用margin: 0 auto;居中;
          3. 下面兩塊用float或者inline-block不換行;
          4. 用margin調(diào)整位置使他們居中。

          第二種全屏的品字布局:

          上面的div設(shè)置成100%,下面的div分別寬50%,然后使用float或者inline使其不換行。

          13 、常見的兼容性問題?

          1. 不同瀏覽器的標(biāo)簽?zāi)J(rèn)的margin和padding不一樣。
          2. *{margin:0;padding:0;}
          3. IE6雙邊距bug:塊屬性標(biāo)簽float后,又有橫行的margin情況下,在IE6顯示margin比設(shè)置的大。hack:display:inline;將其轉(zhuǎn)化為行內(nèi)屬性。
          4. 漸進(jìn)識別的方式,從總體中逐漸排除局部。首先,巧妙的使用“9”這一標(biāo)記,將IE瀏覽器從所有情況中分離出來。接著,再次使用“+”將IE8和IE7、IE6分離開來,這樣IE8已經(jīng)獨立識別。
          {background-color:#f1ee18;/*所有識別*/.background-color:#00deff; /*IE6、7、8識別*/+background-color:#a200ff;/*IE6、7識別*/_background-color:#1e0bd1;/*IE6識別*/}
          1. 設(shè)置較小高度標(biāo)簽(一般小于10px),在IE6,IE7中高度超出自己設(shè)置高度。hack:給超出高度的標(biāo)簽設(shè)置overflow:hidden;或者設(shè)置行高line-height 小于你設(shè)置的高度。
          2. IE下,可以使用獲取常規(guī)屬性的方法來獲取自定義屬性,也可以使用getAttribute()獲取自定義屬性;Firefox下,只能使用getAttribute()獲取自定義屬性。解決方法:統(tǒng)一通過getAttribute()獲取自定義屬性。
          3. Chrome 中文界面下默認(rèn)會將小于 12px 的文本強(qiáng)制按照 12px 顯示,可通過加入 CSS 屬性 -webkit-text-size-adjust: none; 解決。
          4. 超鏈接訪問過后hover樣式就不出現(xiàn)了,被點擊訪問過的超鏈接樣式不再具有hover和active了。解決方法是改變CSS屬性的排列順序:L-V-H-A ( love hate ): a:link {} a:visited {} a:hover {} a:active {}


          14、 為什么要初始化CSS樣式

          因為瀏覽器的兼容問題,不同瀏覽器對有些標(biāo)簽的默認(rèn)值是不同的,如果沒對CSS初始化往往會出現(xiàn)瀏覽器之間的頁面顯示差異。

          15、 absolute的containing block計算方式跟正常流有什么不同?

          無論屬于哪種,都要先找到其祖先元素中最近的 position 值不為 static 的元素,然后再判斷:

          1. 若此元素為 inline 元素,則 containing block 為能夠包含這個元素生成的第一個和最后一個 inline box 的 padding box (除 margin, border 外的區(qū)域) 的最小矩形;
          2. 否則,則由這個祖先元素的 padding box 構(gòu)成。

          如果都找不到,則為 initial containing block。

          補(bǔ)充:

          1. static(默認(rèn)的)/relative:簡單說就是它的父元素的內(nèi)容框(即去掉padding的部分)
          2. absolute: 向上找最近的定位為absolute/relative的元素
          3. fixed: 它的containing block一律為根元素(html/body)


          16、CSS里的visibility屬性有個collapse屬性值?在不同瀏覽器下以后什么區(qū)別?

          當(dāng)一個元素的visibility屬性被設(shè)置成collapse值后,對于一般的元素,它的表現(xiàn)跟hidden是一樣的。

          1. chrome中,使用collapse值和使用hidden沒有區(qū)別。
          2. firefox,opera和IE,使用collapse值和使用display:none沒有什么區(qū)別。


          17、 display:none與visibility:hidden的區(qū)別?

          display:none 不顯示對應(yīng)的元素,在文檔布局中不再分配空間(回流+重繪)

          visibility:hidden 隱藏對應(yīng)元素,在文檔布局中仍保留原來的空間(重繪)

          18、 position跟display、overflow、float這些特性相互疊加后會怎么樣?

          display屬性規(guī)定元素應(yīng)該生成的框的類型;position屬性規(guī)定元素的定位類型;float屬性是一種布局方式,定義元素在哪個方向浮動。

          類似于優(yōu)先級機(jī)制:position:absolute/fixed優(yōu)先級最高,有他們在時,float不起作用,display值需要調(diào)整。float 或者absolute定位的元素,只能是塊元素或表格。

          19 、對BFC規(guī)范(塊級格式化上下文:block formatting context)的理解?

          BFC規(guī)定了內(nèi)部的Block Box如何布局。

          定位方案:

          1. 內(nèi)部的Box會在垂直方向上一個接一個放置。
          2. Box垂直方向的距離由margin決定,屬于同一個BFC的兩個相鄰Box的margin會發(fā)生重疊。
          3. 每個元素的margin box 的左邊,與包含塊border box的左邊相接觸。
          4. BFC的區(qū)域不會與float box重疊。
          5. BFC是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。
          6. 計算BFC的高度時,浮動元素也會參與計算。

          滿足下列條件之一就可觸發(fā)BFC

          1. 根元素,即html
          2. float的值不為none(默認(rèn))
          3. overflow的值不為visible(默認(rèn))
          4. display的值為inline-block、table-cell、table-caption
          5. position的值為absolute或fixed


          20、 為什么會出現(xiàn)浮動和什么時候需要清除浮動?清除浮動的方式?

          浮動元素碰到包含它的邊框或者浮動元素的邊框停留。由于浮動元素不在文檔流中,所以文檔流的塊框表現(xiàn)得就像浮動框不存在一樣。浮動元素會漂浮在文檔流的塊框上。

          浮動帶來的問題:

          1. 父元素的高度無法被撐開,影響與父元素同級的元素
          2. 與浮動元素同級的非浮動元素(內(nèi)聯(lián)元素)會跟隨其后
          3. 若非第一個元素浮動,則該元素之前的元素也需要浮動,否則會影響頁面顯示的結(jié)構(gòu)。

          清除浮動的方式:

          1. 父級div定義height
          2. 最后一個浮動元素后加空div標(biāo)簽 并添加樣式clear:both。
          3. 包含浮動元素的父標(biāo)簽添加樣式overflow為hidden或auto。
          4. 父級div定義zoom


          21、 上下margin重合的問題

          在重合元素外包裹一層容器,并觸發(fā)該容器生成一個BFC。

          例子:

          <div class="aside"></div>
          <div class="text">
           <div class="main"></div>
          </div>
          <!--下面是css代碼--> 
          .aside { 
          margin-bottom: 100px; 
           width: 100px; 
           height: 150px; 
           background: #f66;
           } 
          .main { 
           margin-top: 100px; 
           height: 200px; 
           background: #fcc;
           }
           .text{ 
           /*盒子main的外面包一個div,
          通過改變此div的屬性使兩個盒子分屬于兩個不同的BFC,
          以此來阻止margin重疊*/
           overflow: hidden; 
          //此時已經(jīng)觸發(fā)了BFC屬性。
           }
          


          22、設(shè)置元素浮動后,該元素的display值是多少?

          自動變成display:block

          23、 移動端的布局用過媒體查詢嗎?

          通過媒體查詢可以為不同大小和尺寸的媒體定義不同的css,適應(yīng)相應(yīng)的設(shè)備的顯示。

          1. <head>里邊
          2. <link rel="stylesheet" type="text/css" href="xxx.css" media="only screen and (max-device-width:480px)">
          3. CSS : @media only screen and (max-device-width:480px) {/css樣式/}


          24 、使用 CSS 預(yù)處理器嗎?

          Less sass

          25、 CSS優(yōu)化、提高性能的方法有哪些?

          1. 避免過度約束
          2. 避免后代選擇符
          3. 避免鏈?zhǔn)竭x擇符
          4. 使用緊湊的語法
          5. 避免不必要的命名空間
          6. 避免不必要的重復(fù)
          7. 最好使用表示語義的名字。一個好的類名應(yīng)該是描述他是什么而不是像什么
          8. 避免!important,可以選擇其他選擇器
          9. 盡可能的精簡規(guī)則,你可以合并不同類里的重復(fù)規(guī)則


          26、 瀏覽器是怎樣解析CSS選擇器的?

          CSS選擇器的解析是從右向左解析的。若從左向右的匹配,發(fā)現(xiàn)不符合規(guī)則,需要進(jìn)行回溯,會損失很多性能。若從右向左匹配,先找到所有的最右節(jié)點,對于每一個節(jié)點,向上尋找其父節(jié)點直到找到根元素或滿足條件的匹配規(guī)則,則結(jié)束這個分支的遍歷。

          兩種匹配規(guī)則的性能差別很大,是因為從右向左的匹配在第一步就篩選掉了大量的不符合條件的最右節(jié)點(葉子節(jié)點),而從左向右的匹配規(guī)則的性能都浪費在了失敗的查找上面。

          而在 CSS 解析完畢后,需要將解析的結(jié)果與 DOM Tree 的內(nèi)容一起進(jìn)行分析建立一棵 Render Tree,最終用來進(jìn)行繪圖。在建立 Render Tree 時(WebKit 中的「Attachment」過程),瀏覽器就要為每個 DOM Tree 中的元素根據(jù) CSS 的解析結(jié)果(Style Rules)來確定生成怎樣的 Render Tree。

          27 、在網(wǎng)頁中的應(yīng)該使用奇數(shù)還是偶數(shù)的字體?為什么呢?

          使用偶數(shù)字體。偶數(shù)字號相對更容易和 web 設(shè)計的其他部分構(gòu)成比例關(guān)系。Windows 自帶的點陣宋體(中易宋體)從 Vista 開始只提供 12、14、16 px 這三個大小的點陣,而 13、15、17 px時用的是小一號的點。(即每個字占的空間大了 1 px,但點陣沒變),于是略顯稀疏。

          28、 margin和padding分別適合什么場景使用?

          何時使用margin:

          1. 需要在border外側(cè)添加空白
          2. 空白處不需要背景色
          3. 上下相連的兩個盒子之間的空白,需要相互抵消時。

          何時使用padding:

          1. 需要在border內(nèi)側(cè)添加空白
          2. 空白處需要背景顏色
          3. 上下相連的兩個盒子的空白,希望為兩者之和。

          兼容性的問題:在IE5 IE6中,為float的盒子指定margin時,左側(cè)的margin可能會變成兩倍的寬度。通過改變padding或者指定盒子的display:inline解決。

          29 、元素豎向的百分比設(shè)定是相對于容器的高度嗎?

          當(dāng)按百分比設(shè)定一個元素的寬度時,它是相對于父容器的寬度計算的,但是,對于一些表示豎向距離的屬性,例如 padding-top , padding-bottom , margin-top , margin-bottom 等,當(dāng)按百分比設(shè)定它們時,依據(jù)的也是父容器的寬度,而不是高度。

          30 、全屏滾動的原理是什么?用到了CSS的哪些屬性?

          1. 原理:有點類似于輪播,整體的元素一直排列下去,假設(shè)有5個需要展示的全屏頁面,那么高度是500%,只是展示100%,剩下的可以通過transform進(jìn)行y軸定位,也可以通過margin-top實現(xiàn)
          2. overflow:hidden;transition:all 1000ms ease;


          31、 什么是響應(yīng)式設(shè)計?響應(yīng)式設(shè)計的基本原理是什么?如何兼容低版本的IE?

          響應(yīng)式網(wǎng)站設(shè)計(Responsive Web design)是一個網(wǎng)站能夠兼容多個終端,而不是為每一個終端做一個特定的版本。

          基本原理是通過媒體查詢檢測不同的設(shè)備屏幕尺寸做處理。

          頁面頭部必須有meta聲明的viewport。

          <meta name=’viewport’ content=”width=device-width, 
          initial-scale=1. maximum-scale=1,user-scalable=no”>
          


          32、 視差滾動效果?

          視差滾動(Parallax Scrolling)通過在網(wǎng)頁向下滾動的時候,控制背景的移動速度比前景的移動速度慢來創(chuàng)建出令人驚嘆的3D效果。

          1. CSS3實現(xiàn)
          2. 優(yōu)點:開發(fā)時間短、性能和開發(fā)效率比較好,缺點是不能兼容到低版本的瀏覽器
          3. jQuery實現(xiàn)
          4. 通過控制不同層滾動速度,計算每一層的時間,控制滾動效果。
          5. 優(yōu)點:能兼容到各個版本的,效果可控性好
          6. 缺點:開發(fā)起來對制作者要求高
          7. 插件實現(xiàn)方式
          8. 例如:parallax-scrolling,兼容性十分好


          33、 ::before 和 :after中雙冒號和單冒號有什么區(qū)別?解釋一下這2個偽元素的作用

          1. 單冒號(:)用于CSS3偽類,雙冒號(::)用于CSS3偽元素。
          2. ::before就是以一個子元素的存在,定義在元素主體內(nèi)容之前的一個偽元素。并不存在于dom之中,只存在在頁面之中。

          :before 和 :after 這兩個偽元素,是在CSS2.1里新出現(xiàn)的。起初,偽元素的前綴使用的是單冒號語法,但隨著Web的進(jìn)化,在CSS3的規(guī)范里,偽元素的語法被修改成使用雙冒號,成為::before ::after

          34、 你對line-height是如何理解的?

          行高是指一行文字的高度,具體說是兩行文字間基線的距離。CSS中起高度作用的是height和line-height,沒有定義height屬性,最終其表現(xiàn)作用一定是line-height。

          單行文本垂直居中:把line-height值設(shè)置為height一樣大小的值可以實現(xiàn)單行文字的垂直居中,其實也可以把height刪除。

          多行文本垂直居中:需要設(shè)置display屬性為inline-block。

          35 、怎么讓Chrome支持小于12px 的文字?

          p{font-size:10px;-webkit-transform:scale(0.8);} //0.8是縮放比例
          


          36、 讓頁面里的字體變清晰,變細(xì)用CSS怎么做?

          -webkit-font-smoothing在window系統(tǒng)下沒有起作用,但是在IOS設(shè)備上起作用-webkit-font-smoothing:antialiased是最佳的,灰度平滑。

          37、 position:fixed;在android下無效怎么處理?

          <meta name="viewport" content="width=device-width, 
          initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,
           user-scalable=no"/>
          

          38、 如果需要手動寫動畫,你認(rèn)為最小時間間隔是多久,為什么?

          多數(shù)顯示器默認(rèn)頻率是60Hz,即1秒刷新60次,所以理論上最小間隔為1/60*1000ms = 16.7ms。

          39、 li與li之間有看不見的空白間隔是什么原因引起的?有什么解決辦法?

          行框的排列會受到中間空白(回車空格)等的影響,因為空格也屬于字符,這些空白也會被應(yīng)用樣式,占據(jù)空間,所以會有間隔,把字符大小設(shè)為0,就沒有空格了。

          解決方法:

          1. 可以將<li>代碼全部寫在一排
          2. 浮動li中float:left
          3. 在ul中用font-size:0(谷歌不支持);可以使用letter-space:-3px

          40、 display:inline-block 什么時候會顯示間隙?

          1. 有空格時候會有間隙 解決:移除空格
          2. margin正值的時候 解決:margin使用負(fù)值
          3. 使用font-size時候 解決:font-size:0、letter-spacing、word-spacing

          41、 有一個高度自適應(yīng)的div,里面有兩個div,一個高度100px,希望另一個填滿剩下的高度

          外層div使用position:relative;高度要求自適應(yīng)的div使用position: absolute; top: 100px; bottom: 0; left: 0

          42、 png、jpg、gif 這些圖片格式解釋一下,分別什么時候用。有沒有了解過webp?

          1. png是便攜式網(wǎng)絡(luò)圖片(Portable Network Graphics)是一種無損數(shù)據(jù)壓縮位圖文件格式.優(yōu)點是:壓縮比高,色彩好。 大多數(shù)地方都可以用。
          2. jpg是一種針對相片使用的一種失真壓縮方法,是一種破壞性的壓縮,在色調(diào)及顏色平滑變化做的不錯。在www上,被用來儲存和傳輸照片的格式。
          3. gif是一種位圖文件格式,以8位色重現(xiàn)真色彩的圖像。可以實現(xiàn)動畫效果.
          4. webp格式是谷歌在2010年推出的圖片格式,壓縮率只有jpg的2/3,大小比png小了45%。缺點是壓縮的時間更久了,兼容性不好,目前谷歌和opera支持。

          43、 style標(biāo)簽寫在body后與body前有什么區(qū)別?

          頁面加載自上而下 當(dāng)然是先加載樣式。

          寫在body標(biāo)簽后由于瀏覽器以逐行方式對HTML文檔進(jìn)行解析,當(dāng)解析到寫在尾部的樣式表(外聯(lián)或?qū)懺趕tyle標(biāo)簽)會導(dǎo)致瀏覽器停止之前的渲染,等待加載且解析樣式表完成之后重新渲染,在windows的IE下可能會出現(xiàn)FOUC現(xiàn)象(即樣式失效導(dǎo)致的頁面閃爍問題)

          44、 CSS屬性overflow屬性定義溢出元素內(nèi)容區(qū)的內(nèi)容會如何處理?

          參數(shù)是scroll時候,必會出現(xiàn)滾動條。

          參數(shù)是auto時候,子元素內(nèi)容大于父元素時出現(xiàn)滾動條。

          參數(shù)是visible時候,溢出的內(nèi)容出現(xiàn)在父元素之外。

          參數(shù)是hidden時候,溢出隱藏。

          45、 闡述一下CSS Sprites

          將一個頁面涉及到的所有圖片都包含到一張大圖中去,然后利用CSS的 background-image,background- repeat,background-position 的組合進(jìn)行背景定位。利用CSS Sprites能很好地減少網(wǎng)頁的http請求,從而大大的提高頁面的性能;CSS Sprites能減少圖片的字節(jié)。

          情提示:以下代碼是我們邀請的前端架構(gòu)師基于天貓門戶編寫的css相關(guān)代碼,現(xiàn)在免費分享給大家,獲取的方式為:

          關(guān)注此頭條號“互聯(lián)網(wǎng)IT信息”——>私信發(fā)送 “天貓css” ,(注意:css全是小寫)即可得到源代碼的獲取方式。

          1. 此篇文章講解目錄:

          • 案例和由此案例重點講解的知識點介紹

          • 案例代碼實現(xiàn)

          • css三大特性知識點詳解

          2. 案例和相關(guān)知識點介紹

          此案例是頁面,效果如下:

          此頁面的技術(shù)實現(xiàn)解析:

          使用標(biāo)簽選擇器定義通用樣式,通過css層疊性和繼承性來讓通用標(biāo)簽的樣式被繼承到類選擇器上

          此案例中主要用到了,基于此,我們會系統(tǒng)的將如下知識點全部講解:

          css三大特性:層疊性、繼承性、優(yōu)先級

          3. 此案例的代碼實現(xiàn)

          第一步:使用塊級標(biāo)簽和無序列表編寫導(dǎo)航側(cè)邊欄的html

          第二步:通過標(biāo)簽選擇器定義ul li a的通用樣式

          第三步:定義外層div樣式

          第四步:通過類選擇器定義無序列表樣式,其中l(wèi)i和a標(biāo)簽的基本樣式繼承自第二步的標(biāo)簽選擇器

          4. 此案例的知識點詳解

          CSS三大特性:

          層疊性、繼承性、優(yōu)先級

          1)層疊性:

          1. 給一個標(biāo)簽設(shè)置的樣式發(fā)生沖突的時候即樣式的覆蓋

          2. 瀏覽器的渲染機(jī)制是從上到下的,當(dāng)有沖突的時候就采用最后的那個樣式

          例如:

          h2.grape {color: purple;}

          h2 {color: siver;}

          層疊性代碼實例:

          <!DOCTYPEhtml>

          <htmllang="en">

          <head>

          <metacharset="UTF-8">

          <title>Document</title>

          <styletype="text/css">

          .two{

          color: green;

          }

          .one{

          color: red;

          font-size: 30px;

          }

          .tree{

          color: yellow;

          font-size: 40px;

          }

          </style>

          </head>

          <body>

          <pclass="one two tree">

          一段文字

          </p>

          </body>

          </html>

          2)繼承性:繼承就是子標(biāo)簽繼承了上級標(biāo)簽的CSS樣式的屬性

          1,發(fā)生的前提是:標(biāo)簽之間屬于一種嵌套關(guān)系

          2,文字顏色可以之間繼承

          3,字體大小可以繼承

          4,字體可以繼承

          5,行高也可以實現(xiàn)繼承

          6, 與文字有關(guān)的屬性都可以,實現(xiàn)繼承

          特殊注意:

          a標(biāo)簽超鏈接不能實現(xiàn)字體顏色的繼承,字體大小可以繼承

          h1不可以繼承文字的大小,繼承過來還會做一個計算

          繼承性代碼實例:

          <!DOCTYPEhtml>

          <html>

          <head>

          <metacharset="UTF-8">

          <title></title>

          <style>

          div{

          color: red;

          font-size: 30px;

          }

          </style>

          </head>

          <body>

          <div>

          <ahref="">a</a>

          </div>

          </body>

          </html>

          3) 優(yōu)先級

          具體解釋如下:

          內(nèi)聯(lián)樣式最大,內(nèi)聯(lián)樣式的優(yōu)先級最高。

          ID選擇器的優(yōu)先級,僅次于內(nèi)聯(lián)樣式。

          類選擇器優(yōu)先級低于ID選擇器

          標(biāo)簽選擇器低于類選擇器。

          補(bǔ)充:

          權(quán)重相同時,CSS遵循就近原則。也就是說靠近元素的樣式具有最大的優(yōu)先級,或者說排在最后的樣式優(yōu)先級最大。

          所有都相同時,聲明靠后的優(yōu)先級大。

          CSS定義了一個!important命令,該命令被賦予最大的優(yōu)先級。也就是說不管權(quán)重如何以及樣式位置的遠(yuǎn)近,!important都具有最大優(yōu)先級。

          綜述:

          -行內(nèi)樣式 > 頁內(nèi)樣式 > 外部引用樣式 > 瀏覽器默認(rèn)樣式

          important > 內(nèi)聯(lián) > ID > 偽類|類 | 屬性選擇 > 標(biāo)簽 > 偽對象 > 通配符 > 繼承

          css優(yōu)先級代碼實例:

          <!DOCTYPE>

          <html>

          <head>

          <metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/>

          <title>無標(biāo)題文檔</title>

          <style>

          *{ font-size:56px;}

          p{ font-size:32px; color:#60C;}

          .d{ color:#F0F;}

          #hei{ color:#96F;}

          </style>

          </head>

          <body>

          <h1>我是標(biāo)題</h1>

          <p>我是段落</p>

          <p>我是段落2</p>

          <pclass="d"id="hei"style="color:#FF0;">我是段落3</p>

          <ahref="#">我是超鏈接</a>

          <span>我是備胎標(biāo)簽</span>

          </body>

          </html>

          大家好接下來我們會邀請前端架構(gòu)師以連載的方式,并且結(jié)合阿里天貓商城的門戶,系統(tǒng)講解Css的專業(yè)知識,歡迎大家關(guān)注頭條號“互聯(lián)網(wǎng)IT信息”。


          主站蜘蛛池模板: 一区二区三区人妻无码 | 亚洲AV色香蕉一区二区| 立川理惠在线播放一区| 无码精品不卡一区二区三区| 国产一区二区精品久久| 无码人妻精品一区二区三区99仓本| 国产在线精品一区免费香蕉 | 综合无码一区二区三区| 国产高清不卡一区二区| 人妻无码一区二区三区AV| 人妻少妇精品视频三区二区一区| 午夜视频在线观看一区二区| 无码人妻一区二区三区精品视频| 一区视频免费观看| 91一区二区视频| 一区二区不卡久久精品| 蜜桃视频一区二区三区在线观看| 精品无码一区二区三区水蜜桃| 无码少妇一区二区三区芒果| 国产精品亚洲午夜一区二区三区| 美女福利视频一区| 91精品一区二区三区久久久久 | 精品无码人妻一区二区免费蜜桃| 综合人妻久久一区二区精品| 色噜噜AV亚洲色一区二区| 精品亚洲一区二区| 亚洲一区二区三区在线网站| 五十路熟女人妻一区二区 | 国产精品无码一区二区三区在| 亚洲av无码一区二区三区人妖 | 日韩一区二区三区视频| 成人日韩熟女高清视频一区| 日韩精品无码一区二区中文字幕| 精品国产一区AV天美传媒| 无码一区二区三区中文字幕| 无码精品人妻一区二区三区影院 | 亚洲色精品三区二区一区| 国产一国产一区秋霞在线观看| 一区二区三区福利视频| 精品永久久福利一区二区| 波多野结衣一区二区三区88|