Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产在线播放不卡,亚洲精品一区二区三区在,亚洲第一免费播放区

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

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

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

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

          一、CSS篇

          1、什么是 BFC

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

          形成 BFC 的條件

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

          BFC 的特性

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


          2、什么是盒模型

          CSS3中的盒模型有以下兩種:標準盒子模型、IE盒子模型

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

          在標準盒模型性中

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

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

          在IE盒模型性中

          盒子在網頁中實際占用:
          寬=width + margin2
          高=height + margin2

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

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

          • box-sizeing: content-box表示標準盒模型
          • box-sizeing: border-box表示IE盒模型


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

          當需要垂直居中的元素高度未知時,一般采用一下幾種方案實現垂直居中:

          使用絕對定位和transform

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

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

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

          通過table屬性

          css復制代碼<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)
          • 旋轉 (transform)
          • 增加了旋轉,縮放,定位,傾斜,動畫,多背景

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

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

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

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


          6、為什么會出現margin重疊的問題?怎么解決?

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

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

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

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

          (1)兄弟之間重疊

          • 底部元素變為行內盒子:display: inline-block
          • 底部元素設置浮動:float
          • 底部元素的position的值為absolute/fixed

          (2)父子之間重疊

          • 父元素加入:overflow: hidden
          • 父元素添加透明邊框:border:1px solid transparent
          • 子元素變為行內盒子:display: inline-block
          • 子元素加入浮動屬性或定位


          7、flex布局

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

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


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

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

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

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

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

          js復制代碼(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 視口高度單位

          相對視口的尺寸計算結果

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


          9、移動端1px解決方案

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

          css復制代碼/* 手機端實現真正的一像素邊框 */
          .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;
          }
          
          /* 設備像素比 */
          /* 顯示屏最小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;
              }
          }
          
          /* 設備像素比 */
          @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全面屏安全區域問題

          iOS 11

          css復制代碼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復制代碼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、圖片變形問題如何解決

          如果圖片設置的是背景圖

          css復制代碼background-size: cover;
          

          如果是img標簽圖片

          css復制代碼object-fit: cover;
          


          12、css常見布局實現

          可參考:常見的CSS布局


          二、Javascript基礎

          1、JavaScript數據類型

          JavaScript一共有8種數據類型

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

          一種復雜數據類型:Object 里面包含 Function、Array、Date等

          2、JavaScript判斷數據類型的幾種方法

          typeof

          js復制代碼/*
            優點:能夠快速區分基本數據類型
            缺點:不能將Object、Array和Null區分,都返回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復制代碼/*
            優點:能夠區分Array、Object和Function,適合用于判斷自定義的類實例對象
            缺點:Number,Boolean,String基本數據類型不能判斷
          */
          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復制代碼/*
            優點:精準判斷數據類型
            缺點:寫法繁瑣不容易記,推薦進行封裝后使用
          */
          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 操作符的實現原理及實現

          js復制代碼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、數組常用操作方法

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

          5、數組去重

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

          js復制代碼// 利用filter去實現
          Array.prototype.unique1=function() {
              return this.filter((item, index, array)=> {
                  return this.indexOf(item)===index;
              });
          }
          
          js復制代碼Array.prototype.unique2=function() {
              const n={}, r=[]; // n為hash表,r為臨時數組
              for (let i=0; i < this.length; i++) {
                  if (!n[this[i]]) { // 如果hash表中沒有當前項
                      n[this[i]]=true; //存入hash表
                      r.push(this[i]); //把當前數組的當前項push到臨時數組里面
                  }
              }
              return r;
          }
          
          js復制代碼// 返回后的數組順序會亂
          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、執行上下文與作用域、作用域鏈

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

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

          每個函數調用都有自己的上下文。當代碼執行流進入函數時,函數的上下文被推到一個上下文棧上。 在函數執行完之后,上下文棧會彈出該函數上下文,將控制權返還給之前的執行上下文。ECMAScript 程序的執行流就是通過這個上下文棧進行控制的。

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

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

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

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

          此外,局部作用域中定義的變量可用于在局部上下文中替換全局變量??匆豢聪旅孢@個例子:

          js復制代碼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 和一個函數 changeColor()。changeColor()的局部上下文中有一個變量 anotherColor 和一個函數 swapColors(),但在這里可以訪問全局上下文中的變量 color。swapColors()的局部上下文中有一個變量 tempColor,只能在這個上下文中訪問到。全局上下文和changeColor()的局部上下文都無法訪問到 tempColor。而在 swapColors()中則可以訪問另外兩個 上下文中的變量,因為它們都是父上下文。下圖展示了這個例子的作用域鏈。

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

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

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

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


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

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

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

          bind 和 apply、call 區別
          call、apply都是直接調用,bind生成的this指向改變函數需要手動調用

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

          JavaScript深入之從原型到原型鏈


          10、js實現繼承的幾種方法

          比較常見的幾種:

          • 原型鏈繼承
          • 借用構造函數繼承
          • 組合繼承
          • 原型式繼承
          • 寄生式繼承
          • 寄生組合式繼承 一般只建議寄生組合式繼承,因為其它方式的繼承會在一次實例中調用兩次父類的構造函數或有其它缺點,代碼如下:
          js復制代碼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() 擴展運算符(...) Array.prototype.concat() Array.prototype.slice()

          12、事件循環機制/Event Loop

          說說事件循環機制(滿分答案來了)


          13、防抖與節流

          防抖: 防抖就是將一段時間內連續的多次觸發轉化為一次觸發。一般可以使用在用戶輸入停止一段時間過后再去獲取數據,而不是每次輸入都去獲取
          防抖應用場景:

          • 保存、跳轉、登錄等按鈕的頻繁點擊
          • 搜索框搜索


          節流: 節流,顧名思義,控制流量。用于用戶在與頁面交互時控制事件發生的頻率,一般場景是單位的時間或其它間隔內定時執行操作。一段時間內,事件在每次到達我們規定的間隔 n 秒時觸發一次
          節流應用場景:

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


          14、函數柯里化

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

          js復制代碼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
          • 解構賦值
          • 模板字符串
          • 箭頭函數
          • 函數默認值
          • promise
          • set、map結構
          • class類
          • symbol
          • Iterator 和 for...of 循環.
          • 數值的擴展方法
          • 數組的擴展方法
          • 正則的擴展方法
          • 對象的擴展方法


          2、說下var、let、const的區別

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

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


          3、說說你對promise的了解

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

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


          4、setTimeout、Promise、Async/Await 的區別

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

          5、class類的理解

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

          js復制代碼class Person {} // 類聲明
          const Animal=class {}; // 類表達式
          

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

          js復制代碼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 {} 
          

          類構成
          類可以包含構造函數方法、實例方法、獲取函數、設置函數和靜態類方法,但這些都不是必需的。 空的類定義照樣有效。默認情況下,類定義中的代碼都在嚴格模式下執行

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

          類的實例化
          class 的實例化必須通過 new 關鍵字

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

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

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

          js復制代碼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
          在“類”的內部可以使用get和set關鍵字,對某個屬性設置存值函數和取值函數,攔截該屬性的存取行為。

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

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

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

          關鍵字 super
          super關鍵字用于訪問和調用一個對象的父對象上的函數。

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

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



          四、瀏覽器、網絡基礎

          1、如何用js去實現一個ajax

          大概步驟如下,具體要針對具體業務封裝:

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


          2、常見的http狀態碼

          狀態碼

          含義

          200

          表示從客戶端發來的請求在服務器端被正常處理了

          204

          無內容。服務器成功處理,但未返回內容。在未更新網頁的情況下,可確保瀏覽器繼續顯示當前文檔

          301

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

          302

          臨時移動。與301類似。但資源只是臨時被移動。客戶端應繼續使用原有URI

          304

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

          400

          表示請求報文中存在語法錯誤。當錯誤發生時,需修改請求的內容后再次發送請求

          401

          表示未授權(Unauthorized),當前請求需要用戶驗證

          403

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

          404

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

          500

          表示服務器端在執行請求時發生了錯誤。也有可能是Web應用存在的bug或某些臨時的故障

          502

          作為網關或者代理工作的服務器嘗試執行請求時,從遠程服務器接收到了一個無效的響應

          503

          表示服務器暫時處于超負載或正在進行停機維護,現在無法處理請求

          504

          網關超時, 服務器作為網關或代理,但是沒有及時從上游服務器收到請求

          3、ajax的請求頭和響應頭包含哪些東西

          Request header

          解釋

          Accept

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

          Accept-Encoding

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

          Accept-Language

          瀏覽器所希望的語言種類

          Cache-Control

          緩存機制,默認no-cache

          Connec-Length

          請求頭的長度

          Content-Type

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

          Connection

          表示是否需要持久連接。(HTTP 1.1默認進行持久連接)

          Cookie

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

          Host

          指定請求的服務器的域名和端口號

          If-Modified-Since

          只有當所請求的內容在指定的日期之后又經過修改才返回它,否則返回304“Not Modified”應答

          Referer

          包含一個URL,用戶從該URL代表的頁面出發訪問當前請求的頁面

          User-Agent

          瀏覽器信息,如果Servlet返回的內容與瀏覽器類型有關則該值非常有用

          Cookie

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


          Response header

          解釋

          Allow

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

          Content-Encoding

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

          Content-Length

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

          Content-Type

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

          Date

          當前的GMT時間。你可以用setDateHeader來設置這個頭以避免轉換時間格式的麻煩

          Expires

          應該在什么時候認為文檔已經過期,從而不再緩存它?

          Last-Modified

          文檔的最后改動時間??蛻艨梢酝ㄟ^If-Modified-Since請求頭提供一個日期,
          該請求將被視為一個條件GET,只有改動時間遲于指定時間的文檔才會返回,
          否則返回一個304(Not Modified)狀態。Last-Modified也可用setDateHeader方法來設置。

          Location

          表示客戶應當到哪里去提取文檔。Location通常不是直接設置的,而是通過HttpServletResponse的sendRedirect方法,該方法同時設置狀態代碼為302

          Refresh

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

          Server

          服務器名字。Servlet一般不設置這個值,而是由Web服務器自己設置

          Set-Cookie

          設置和頁面關聯的Cookie。Servlet不應使用response.setHeader("Set-Cookie", ...),而是應使用HttpServletResponse提供的專用方法addCookie

          WWW-Authenticate

          客戶應該在Authorization頭中提供什么類型的授權信息?
          在包含401(Unauthorized)狀態行的應答中這個頭是必需的

          4、為什么會產生跨域?怎么去解決跨域問題?

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

          跨域解決方案:

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

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


          5、post的預請求了解過嗎?

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

          什么情況下發生

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

          例如設置了post請求的content-type:application/json,就會發生預請求


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

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

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


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

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

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

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

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

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


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

          大概流程如下:

          1. 第一次請求,無緩存,直接向服務器發請求,并將請求結果存入緩存中
          2. 第二次請求,在強制緩存時間內,緩存未過期,瀏覽器接使用緩存作為結果返回 200
          3. 第三次請求,強制緩存時間已過期,進入協商緩存,向服務器請求,通過在Header中攜帶 If-Modified-Since(對應瀏覽器返回的last-Modify) 或If-None-Match(對應瀏覽器返回的Etag) 校驗緩存內容是否有更新,Etag優先級更高
          4. 緩存資源沒有更新,返回 304,瀏覽器繼續使用緩存,更新強制緩存時間
            緩存資源有更新,緩存失效,返回 200,重新返回資源和緩存標識,再存入瀏覽器緩存中


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

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

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

          Cookie主要構成

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

          Cookie的原理

          第一次訪問網站時,瀏覽器發出請求,服務器響應請求后,會在響應頭中添加一個Set-Cookie,將cookie放入響應請求中。

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

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

          Cookie的生成

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

          • 服務端設置Cookie
          • 客戶端設置Cookie

          服務端設置方式參考上面Cookie的原理,具體的實現方式自行查閱相關資料??蛻舳嗽O置Cookie方法如下:

          js復制代碼document.cookie="name=zhangsan; age=20"
          

          Cookie的缺點

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

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

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

          使用方法:

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

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

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

          使用方法:

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

          sessionStorage和localStorage的區別:localStorage的數據可以長期保留,sessionStorage的數據在關閉頁面后即被清空

          IndexedDB
          IndexedDB,全稱Indexed Database API,是瀏覽器中保持結構化數據的一種數據庫。
          IndexedDB的思想是創建一套API,方便保存和讀取JavaScript對象,同時支持查詢和搜索。

          IndexedDB特點

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

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

          總結

          • Cookie主要用于“維持狀態”,而非本地存儲數據
          • Web Storage是專門為瀏覽器提供的數據存儲機制,不與服務端發生通信
          • IndexedDB 用于客戶端存儲大量結構化數據


          10、瀏覽器垃圾回收機制

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

          不再使用的變量也就是生命周期結束的變量,當然只可能是局部變量,全局變量的生命周期直至瀏覽器卸載頁面才會結束。局部變量只在函數的執行過程中存在,而在這個過程中會為局部變量在?;蚨焉戏峙湎鄳目臻g,以存儲它們的值,然后在函數中使用這些變量,直至函數結束,而閉包中由于內部函數的原因,外部函數并不能算是結束。

          還是上代碼說明吧:

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

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

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

          標記清除
          js中最常用的垃圾回收方式就是標記清除。當變量進入環境時,例如,在函數中聲明一個變量,就將這個變量標記為“進入環境”。從邏輯上講,永遠不能釋放進入環境的變量所占用的內存,因為只要執行流進入相應的環境,就可能會用到它們。而當變量離開環境時,則將其標記為“離開環境”。

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

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

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

          Netscape Navigator3是最早使用引用計數策略的瀏覽器,但很快它就遇到一個嚴重的問題:循環引用。循環引用指的是對象A中包含一個指向對象B的指針,而對象B中也包含一個指向對象A的引用。

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

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

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

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

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

          舉個栗子:

          js復制代碼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方法會引用外部環境中的變量,自然也包括obj,是不是很隱蔽啊。(在比較新的瀏覽器中在移除Node的時候已經會移除其上的event了,但是在老的瀏覽器,特別是ie上會有這個bug)

          解決辦法:

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

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

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

          要注意的是,IE9+并不存在循環引用導致Dom內存泄露問題,可能是微軟做了優化,或者Dom的回收方式已經改變

          11、談談你對重繪和回流的理解

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

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

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

          回流 (Reflow)

          當Render Tree中部分或全部元素的尺寸、結構、或某些屬性發生改變時,瀏覽器重新渲染部分或全部文檔的過程稱為回流。

          會導致回流的操作:

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

          一些常用且會導致回流的屬性和方法:

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

          重繪 (Repaint)

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

          性能影響

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

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

          現代瀏覽器會對頻繁的回流或重繪操作進行優化:

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

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

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

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

          如何避免

          CSS

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

          JavaScript

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


          12、http和https的區別

          • HTTP是明文傳輸,不安全的,HTTPS是加密傳輸,安全的多
          • HTTP標準端口是80,HTTPS標準端口是443
          • HTTP不用認證證書免費,HTTPS需要認證證書要錢
          • 連接方式不同,HTTP三次握手,HTTPS中TLS1.2版本7次,TLS1.3版本6次
          • HTTP在OSI網絡模型中是在應用層,而HTTPS的TLS是在傳輸層
          • HTTP是無狀態的,HTTPS是有狀態的


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

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


          14、DNS

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


          15、CDN

          CDN是什么?使用CDN有什么優勢?


          五、Vue

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

          Vue.js 技術揭秘

          六、React

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

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

          搞懂這12個Hooks,保證讓你玩轉React

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

          React Hooks 原理

          深入理解 React 高階組件

          七、性能優化

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

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

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

          渲染優化:設置viewport、減少DOM節點、優化動畫、優化高頻事件、GPU加速

          樣式優化:避免在HTML中書寫style、避免CSS表達式、移除CSS空規則、正確使用display:display、不濫用float等

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

          加載優化

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

          執行優化

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

          渲染優化

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

          樣式優化

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

          腳本優化

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

          八、webpack

          Webpack面試題

          當面試官問Webpack的時候他想知道什么


          九、TypeScript

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


          十、數據結構與算法

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

          JavaScript 數據結構與算法之美

          十一、前端安全

          1、說一說XSS攻擊

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

          存儲型(server端)

          場景:見于帶有用戶保存數據的網站功能,如論壇發帖、商品評論、用戶私信等

          攻擊步驟:

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

          反射型(Server端)

          與存儲型的區別在于,存儲型的惡意代碼存儲在數據庫中,反射型的惡意代碼在URL上

          場景:通過 URL 傳遞參數的功能,如網站搜索、跳轉等

          攻擊步驟:

          1. 攻擊者構造出特殊的 URL,其中包含惡意代碼
          2. 用戶打開帶有惡意代碼的 URL 時,網站服務端將惡意代碼從 URL 中取出,拼接在 HTML 中返回給瀏覽器
          3. 用戶瀏覽器接收到響應后解析執行,混在其中的惡意代碼也被執行
          4. 惡意代碼竊取用戶數據并發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作

          Dom 型(瀏覽器端)

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

          場景:通過 URL 傳遞參數的功能,如網站搜索、跳轉等

          攻擊步驟:

          1. ?攻擊者構造出特殊的 URL,其中包含惡意代碼
          2. ?用戶打開帶有惡意代碼的 URL
          3. ?用戶瀏覽器接收到響應后解析執行,前端 JavaScript 取出 URL 中的惡意代碼并執行
          4. ?惡意代碼竊取用戶數據并發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作

          預防方案:
          防止攻擊者提交惡意代碼,防止瀏覽器執行惡意代碼

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

          2、說一說CSRF攻擊

          攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站發送跨站請求。利用受害者在被攻擊網站已經獲取的注冊憑證,繞過后臺的用戶驗證,達到冒充用戶對被攻擊的網站執行某項操作的目的

          攻擊流程舉例

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

          攻擊類型

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

          預防方案:

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

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


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

          、 介紹一下標準的CSS的盒子模型?與低版本IE的盒子模型有什么不同的?

          標準盒子模型:寬度=內容的寬度(content)+ border + padding + margin

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

          2、 box-sizing屬性?

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

          context-box:W3C的標準盒子模型,設置元素的 height/width 屬性指的是content部分的高/寬

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

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

          CSS選擇符:id選擇器(#myid)、類選擇器(.myclassname)、標簽選擇器(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

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

          !important 比內聯優先級高

          4、 CSS優先級算法如何計算?

          元素選擇符: 1

          class選擇符: 10

          id選擇符:100

          元素標簽:1000

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


          5、 CSS3新增偽類有那些?

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

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

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

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

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

          :enabled :disabled 表單控件的禁用狀態。

          :checked 單選框或復選框被選中。

          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; 
          

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

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

          inline(默認)--內聯

          none--隱藏

          block--塊顯示

          table--表格顯示

          list-item--項目列表

          inline-block

          8、 position的值?

          static(默認):按照正常文檔流進行排列;

          relative(相對定位):不脫離文檔流,參考自身靜態位置通過 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 屬性用于創建圓角
          7. 邊框圖片:border-image: url(border.png) 30 30 round
          8. 盒陰影:box-shadow: 10px 10px 5px #888888
          9. 媒體查詢:定義兩套css,當瀏覽器的尺寸變化時會采用不同的屬性


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

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

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

          11、 用純CSS創建一個三角形的原理是什么?

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

          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、 一個滿屏品字布局如何設計?

          第一種真正的品字:

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

          第二種全屏的品字布局:

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

          13 、常見的兼容性問題?

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


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

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

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

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

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

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

          補充:

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


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

          當一個元素的visibility屬性被設置成collapse值后,對于一般的元素,它的表現跟hidden是一樣的。

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


          17、 display:none與visibility:hidden的區別?

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

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

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

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

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

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

          BFC規定了內部的Block Box如何布局。

          定位方案:

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

          滿足下列條件之一就可觸發BFC

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


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

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

          浮動帶來的問題:

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

          清除浮動的方式:

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


          21、 上下margin重合的問題

          在重合元素外包裹一層容器,并觸發該容器生成一個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; 
          //此時已經觸發了BFC屬性。
           }
          


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

          自動變成display:block

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

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

          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 預處理器嗎?

          Less sass

          25、 CSS優化、提高性能的方法有哪些?

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


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

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

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

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

          27 、在網頁中的應該使用奇數還是偶數的字體?為什么呢?

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

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

          何時使用margin:

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

          何時使用padding:

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

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

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

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

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

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


          31、 什么是響應式設計?響應式設計的基本原理是什么?如何兼容低版本的IE?

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

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

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

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


          32、 視差滾動效果?

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

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


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

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

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

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

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

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

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

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

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


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

          -webkit-font-smoothing在window系統下沒有起作用,但是在IOS設備上起作用-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、 如果需要手動寫動畫,你認為最小時間間隔是多久,為什么?

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

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

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

          解決方法:

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

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

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

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

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

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

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

          43、 style標簽寫在body后與body前有什么區別?

          頁面加載自上而下 當然是先加載樣式。

          寫在body標簽后由于瀏覽器以逐行方式對HTML文檔進行解析,當解析到寫在尾部的樣式表(外聯或寫在style標簽)會導致瀏覽器停止之前的渲染,等待加載且解析樣式表完成之后重新渲染,在windows的IE下可能會出現FOUC現象(即樣式失效導致的頁面閃爍問題)

          44、 CSS屬性overflow屬性定義溢出元素內容區的內容會如何處理?

          參數是scroll時候,必會出現滾動條。

          參數是auto時候,子元素內容大于父元素時出現滾動條。

          參數是visible時候,溢出的內容出現在父元素之外。

          參數是hidden時候,溢出隱藏。

          45、 闡述一下CSS Sprites

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

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

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

          1. 此篇文章講解目錄:

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

          • 案例代碼實現

          • css三大特性知識點詳解

          2. 案例和相關知識點介紹

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

          此頁面的技術實現解析:

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

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

          css三大特性:層疊性、繼承性、優先級

          3. 此案例的代碼實現

          第一步:使用塊級標簽和無序列表編寫導航側邊欄的html

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

          第三步:定義外層div樣式

          第四步:通過類選擇器定義無序列表樣式,其中li和a標簽的基本樣式繼承自第二步的標簽選擇器

          4. 此案例的知識點詳解

          CSS三大特性:

          層疊性、繼承性、優先級

          1)層疊性:

          1. 給一個標簽設置的樣式發生沖突的時候即樣式的覆蓋

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

          例如:

          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)繼承性:繼承就是子標簽繼承了上級標簽的CSS樣式的屬性

          1,發生的前提是:標簽之間屬于一種嵌套關系

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

          3,字體大小可以繼承

          4,字體可以繼承

          5,行高也可以實現繼承

          6, 與文字有關的屬性都可以,實現繼承

          特殊注意:

          a標簽超鏈接不能實現字體顏色的繼承,字體大小可以繼承

          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) 優先級

          具體解釋如下:

          內聯樣式最大,內聯樣式的優先級最高。

          ID選擇器的優先級,僅次于內聯樣式。

          類選擇器優先級低于ID選擇器

          標簽選擇器低于類選擇器。

          補充:

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

          所有都相同時,聲明靠后的優先級大。

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

          綜述:

          -行內樣式 > 頁內樣式 > 外部引用樣式 > 瀏覽器默認樣式

          important > 內聯 > ID > 偽類|類 | 屬性選擇 > 標簽 > 偽對象 > 通配符 > 繼承

          css優先級代碼實例:

          <!DOCTYPE>

          <html>

          <head>

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

          <title>無標題文檔</title>

          <style>

          *{ font-size:56px;}

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

          .d{ color:#F0F;}

          #hei{ color:#96F;}

          </style>

          </head>

          <body>

          <h1>我是標題</h1>

          <p>我是段落</p>

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

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

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

          <span>我是備胎標簽</span>

          </body>

          </html>

          大家好接下來我們會邀請前端架構師以連載的方式,并且結合阿里天貓商城的門戶,系統講解Css的專業知識,歡迎大家關注頭條號“互聯網IT信息”。


          主站蜘蛛池模板: 一区二区三区伦理高清| 日韩在线视频一区| 色欲综合一区二区三区| 国产精品成人免费一区二区| 波多野结衣一区在线| 国产一区二区成人| 国模私拍一区二区三区| 亚洲国产精品一区二区第一页免| 亚洲AV无码一区二区三区牛牛| 国产午夜福利精品一区二区三区| 无码精品人妻一区二区三区影院| 中文字幕日韩精品一区二区三区 | 一区二区中文字幕在线观看| 中文乱码字幕高清一区二区| 日韩av无码一区二区三区| 国产精品日本一区二区不卡视频 | 91久久精品国产免费一区| 中文字幕一区二区三区日韩精品| 亚洲性日韩精品一区二区三区| 波多野结衣中文一区| 日亚毛片免费乱码不卡一区 | 亚洲成AV人片一区二区密柚 | 国产成人一区二区在线不卡| 亚洲AV日韩综合一区| 午夜性色一区二区三区不卡视频| 亚洲a∨无码一区二区| 日韩免费视频一区| 一区二区免费国产在线观看| 亚洲日韩国产一区二区三区| 国产伦精品一区二区三区视频金莲 | 伊人久久精品无码麻豆一区 | 一区二区在线免费视频| 精品亚洲一区二区三区在线播放| 亚洲一区爱区精品无码| 亚洲av无码片区一区二区三区| 精品国产一区二区三区麻豆| 精品少妇人妻AV一区二区| 国产女人乱人伦精品一区二区| www一区二区三区| 日韩亚洲AV无码一区二区不卡| 亚洲中文字幕在线无码一区二区|