1. 程式人生 > >前端基礎精簡總結

前端基礎精簡總結

頂級 frame hub scrip 顯式 流程 pro move 順序

更好閱讀猛戳 這裏

1. JavaScript

1.1. 基礎語法

包括:變量聲明、數據類型、函數、控制語句、內置對象等

1.1.1. 變量聲明

ES5:

var         //普通變量 
function    //函數

ES6新增:

let         //普通變量
const       //靜態變量
import      //模塊
class       //類
1.1.2. 數據類型
-- 類型介紹

ES5:
String、Number、Boolean、Null、Undefined、Object
ES6增:
Symbol
其中,object為引用,其他為基本類型

  • 基本類型
    占據空間固定,是簡單的數據段,將其存儲在
    (stack)中(按值訪問) 便於提升變量查詢速度
    為了便於操作這類數據,ECMAScript提供了 3 個 基本包裝類型 :Boolean、Number 和 String
    • 基本包裝類型
      一種特殊的引用類型,每當讀取一個基本類型值的時候,JS內部就會創建一個對應的包裝對象,從而可以調用一些方法來操作這些數據
  • 引用類型
    • 由於其值的大小會改變,所以不能將其存放在棧中,否則會降低變量查詢速度
    • 將其存儲在(heap)中,存儲在變量處的值是一個指針,指向存儲對象的內存處(按址訪問)
    • 可以為其添加、改變和刪除屬性和方法;但基本類型不可以添加屬性和方法
-- 類型判斷
  • 原始類型
    • typeof
  • 引用類型
    • isinstanceof -- 判斷已知對象
    • constructor -- 根據對象的constructor判斷
      constructor本來是原型對象上的屬性,指向構造函數。但是根據實例對象尋找屬性的順序,若實例對象上沒有實例屬性或方法時,就去原型鏈上尋找,因此,實例對象也是能使用constructor屬性的
    • Object.prototype.toString.call
    • $.type() -- 萬能判斷
    var a = new Array();
    console.log(a instanceof Array) // a是否Array的實例  true
    console.log(a.constructor
    == Array) // a實例所對應的構造函數是否為Array true // constructor屬性是可以被修改的,會導致檢測出的結果不正確 function Dog(){ } function Cat(){ } Cat.prototype = new Dog(); var m= new Cat(); console.log(m.constructor==Cat); // false console.log(John.constructor==Person); // true // instanceof 對於直接或間接引用都是true console.log(m instanceof Cat); // true console.log(John instanceof Person); // true //Object.prototype.toString.call function a() { }; var toString = Object.prototype.toString; console.log(toString.call(new Date) === '[object Date]'); //true console.log(toString.call(new String) ==='[object String]');//true console.log(toString.call(a) ==='[object Function]'); //true //$.type jQuery.type( undefined ) === "undefined" // true jQuery.type() === "undefined" // true jQuery.type( null ) === "null" // true jQuery.type( true ) === "boolean" // true

1.1.3. 函數

  • 普通函數 -- 直接調用
  • 構造函數 -- new 創建對象
  • 對象方法 -- 對象調用

1.1.4. 內置對象

  • window
    • 全局對象,主要描述瀏覽器窗口相關的屬性和狀態
  • Date
  • Array
  • JSON
    • 主要用於對象的序列化和反序列化
    • 實現對象的深拷貝
  • RegExp
-- 淺復制與深拷貝
  1. 淺復制
    對對象地址的復制,並沒有開辟新的棧,復制的結果是兩個對象指向同一個地址,修改其中一個對象的屬性,則另一個對象的屬性也會改變
  2. 深拷貝
    開辟新的棧,兩個對象對應兩個不同的地址,修改一個對象的屬性,不會改變另一個對象的屬性

方法

  1. 遞歸

    var china = {
        nation : '中國',
        birthplaces:['北京','上海','廣州'],
        skincolr :'yellow',
        friends:['sk','ls']
    }
    //深復制,要想達到深復制就需要用遞歸
    function deepCopy(o,c){
        var c = c || {}
        for(var i in o){
            if(typeof o[i] === 'object'){
                //要考慮深復制問題了
                if(o[i].constructor === Array){
                    //這是數組
                    c[i] =[]
                }else{
                    //這是對象
                    c[i] = {}
                }
                deepCopy(o[i],c[i])
            }else{
                c[i] = o[i]
            }
        }
        return c
    }
    var result = {name:'result'}
    result = deepCopy(china,result)
    console.dir(result)

    技術分享圖片

  2. JSON

    var test ={
    name:{
        xing:{ 
            first:'張',
            second:'李'
        },
        ming:'老頭'
    },
    age :40,
    friend :['隔壁老王','宋經紀','同事']
    }
    var result = JSON.parse(JSON.stringify(test))
    result.age = 30
    result.name.xing.first = '往'
    result.friend.push('fdagldf;ghad')
    console.dir(test)
    console.dir(result)

    技術分享圖片

1.2. 函數原型鏈

JS是一種基於對象的語言,但在ES6 之前是不支持繼承的,為了具備繼承的能力,Javascript 在 函數對象上建立了原型對象prototype,並以函數對象為主線,從上至下,在JS內部構建了一條 原型鏈

Object 是所有對象的祖宗, 任何對象所建立的原型鏈最終都指向了Object

簡單來說:
建立了變量查找機制,當訪問一個對象的屬性時,先查找對象本身是否存在,如果不存在就去該對象所在的原型連上去找,直到Object對象為止,如果都沒有找到該屬性才會返回undefined。因此,我們可以通過原型鏈來實現JS繼承

1.3. 函數作用域

變量在聲明它們的函數體以及這個函數體嵌套的任意函數體

JS中沒有塊級作用域,只有函數作用域
導致JS中出現了變量提升的問題
—— 將變量聲明提升到它所在作用域的最開始的部分
為了解決變量提升帶來的副作用,ES6新增了let 命令來聲明變量,let 所聲明的變量只在 let 命令所在的代碼塊內有效,所以不存在變量提升問題

1.4. this 指針

this 指針存在於函數中,用以標識函數運行時所處的上下文

  • 普通函數
    始終指向全局對象window
  • 構造函數
    指向新創建的對象
  • 方法
    指向調用該方法的對象
  • call、apply 和 bind
    方法來改變函數的 this 指向,其中,call 和 apply 主動執行函數,bind一般在事件回調中使用, call 和 apply的區別只是參數的傳遞方式不同

1.5. new 操作符

函數的創建有三種方式,即 顯式聲明、匿名定義 和 new Function()

JS將新對象的原型鏈指向了構造函數的原型對象,於是就在新對象和函數對象之間建立了一條原型鏈,通過新對象可以訪問到函數對象原型prototype中的方法和屬性

1.6. 閉包

具有獨立作用域的靜態執行環境

和函數作用域不同的是:

  • 閉包的作用域
    靜態的,可以永久保存局部資源
  • 函數作用域
    只存在於運行時,函數執行結束後立即銷毀

因此,閉包可以形成一個獨立的執行過程

1.7. 單線程和異步

JavaScript

  • 單線程語言,在瀏覽器中,當JS代碼被加載時,瀏覽器會為其分配一個主線程來執行任務(函數)
    主線程會形成一個全局執行環境,執行環境在棧中采用後進先出(LIFO)的順序來執行代碼塊,以保證所有的函數能按照正確的順序被執行
  • 執行環境中維護了一個異步隊列(也叫工作線程),並將這些耗時任務放入隊列中進行等待
    • 如ajax請求、定時器、事件等
    • 這些任務的執行時機並不確定,只有當主線程的任務執行完成以後,主線程才會去檢查異步隊列中的任務是否需要開始執行。
    • JS中的 setTimeout 和 setInterval 就是典型的異步操作,它們會被放入異步隊列中等待,即使 setTimeout(0)也不會被立即執行,需要等到當前同步任務結束後才會被執行。

1.8. 異步通信

瀏覽器專門用來和服務器進行交互的異步通訊技術

1.8.1. Ajax
  • Ajax是瀏覽器專門用來和服務器進行交互的異步通訊技術
  • 其核心對象是XMLHttpRequest,通過該對象可以創建一個Ajax請求
  • Ajax請求是一個耗時的異步操作,當請求發出以後,Ajax提供了兩個狀態位來描述請求在不同階段的狀態,這兩個狀態位分別是
    • readyState
    • status
      readyState 通過5個狀態碼來描述一個請求的5個階段:
      0 - 請求未發送,初始化階段
      1 - 請求發送中,服務器還未收到請求
      2 - 請求發送成功,服務器已收到請求
      3 - 服務器處理完成,開始響應請求,傳輸數據
      4 - 客戶端收到請求,並完成了數據下載,生成了響應對象
      status
      1XX 提示信息 - 表示請求已被成功接收,繼續處理
      2XX 成功 - 表示請求已被成功接收,理解,接受
      3XX 重定向 - 要完成請求必須進行更進一步的處理
      4XX 客戶端錯誤 - 請求有語法錯誤或請求無法實現
      5XX 服務器端錯誤 - 服務器未能實現合法的請求

常見問題:

  • timeout 只會影響readyState,而不會影響status,因為超時只會中斷數據傳輸,但不會影響服務器的處理結果。 如果 timeout 設置的不合理,就會導致響應碼status 是200,但 response裏卻沒有數據,這種情況就是服務器正確響應了請求,但數據的下載被超時中斷了。

HTTP 相關請見:

  • 學習前端前必知的——HTTP協議詳解

    1.8.2. JSONP && XSS

    瀏覽器設置了安全限制——JavaScript或Cookie只能訪問同域下的內容——同源策略

只允許請求和當前地址同域的服務器資源。但不限制腳本和標簽發送跨域請求,比如script 和 img 標簽,因此可以利用腳本跨域能力來實現跨域請求,即JSONP 的原理。

JSONP雖然可以解決跨域問題,但只能是get請求,並且沒有有效的錯誤捕獲機制
為了解決這個問題,XMLHttpRequest Level2 提出了CORS 模型,即 跨域資源共享, 它不是一個新的API,而是一個標準規範,當瀏覽器發現該請求需要跨域時,就會自動在頭信息中添加一個 Origin字段,用以說明本次請求來自哪個源。服務器根據這個值,決定是否同意這次請求。

隨著移動端的快速發展,Web技術的應用場景正在變得越來越復雜, 關註點分離 原則在系統設計層面就顯得越來越重要,而XMLHttpRequest 是 Ajax 最古老的一個接口,因而不太符合現代化的系統設計理念。因此,瀏覽器提供了一個新的 Ajax 接口,即 Fetch API ,Fetch API 是基於Promise 思想設計的,更符合關註點分離原則。

更多請見:

  • JSONP && CORS 詳解
  • fetch 進階指南
  • JavaScript 異步編程的4種方式

1.9. 模塊化

模塊加載方案,最主要有 CMD 和 AMD 兩種,分別以commonjs 和 requirejs為代表

ES6 在語言標準的層面上,實現了模塊化編程,其設計思想是,盡量靜態化,使得編譯時就能確定模塊的依賴關系,即編譯時加載

CMD和AMD是在運行時確定依賴關系,即運行時加載

詳情:
AMD && CMD

ES6 模塊化

每一個ES6模塊都是一個包含JS代碼的文件,模塊本質上就是一段腳本,而不是用module關鍵字定義一個模塊,但是模塊與腳本還是有兩點區別:

  • 在ES6模塊中,無論你是否加入“use strict;”語句,默認情況下模塊都是在嚴格模式下運行。
  • 在模塊中你可以使用import和export關鍵字。

默認情況下,你在模塊中的所有聲明相對於模塊而言都是寄存在本地的。如果你希望公開在模塊中聲明的內容,並讓其它模塊加以使用,你一定要導出這些功能。想要導出模塊的功能有很多方法,其中最簡單的方式是添加export關鍵字,可以導出所有的最外層函數、類以及var、let或const聲明的變量。

es6中 代碼就是模塊,不是一段腳本,所以所有的聲明都被限定在模塊的作用域中,對所有腳本和模塊全局不可見。你需要做的是將組成模塊公共API的聲明全部導出。

webpack
在編譯時計算所有依賴並將所有模塊打包成一個文件,通過網絡一次傳輸所有模塊
減少加載模塊時的網絡往返時間

深入淺出ES6(模塊):http://www.infoq.com/cn/articles/es6-in-depth-modules

1.10. Node.js

一個基於 Chrome V8 引擎的 JavaScript運行環境

Node.js在服務端的優勢是,它采用單線程和異步I/O模型,實現了一個高並發、高性能的運行時環境。相比傳統的多線程模型,Node.js實現簡單,並且可以減少資源開銷

1.11. ES6

目標是讓JS能夠方便的開發企業級大型應用程序

變化

  • 新增 let、const 命令 來聲明變量
    和var 相比,let聲明的變量不存在變量提升問題,但沒有改變JS弱類型的特點,依然可以接受任意類型變量的聲明;const
    聲明的變量不允許在後續邏輯中改變,提高了JS語法的嚴謹性。
  • 新增解構賦值、rest語法、箭頭函數
    這些都是為了讓代碼看起來更簡潔,而包裝的語法糖。
  • 新增模塊化
    這是JS走向規範比較重要的一步,讓前端更方便的實現工程化。
  • 新增類和繼承的概念
    配合模塊化,JS也可以實現高復用、高擴展的系統架構。
  • 新增模板字符串功能
    高效簡潔,結束拼接字符串的時代。
  • 新增Promise對象
    解決異步回調多層嵌套的問題
    使得原本的多層級的嵌套代碼,變成了鏈式調用 讓代碼更清晰,減少嵌套數

promise

  • 容器:裏面保存著某個未來才會結束的事件(通常是一個異步操作)的結果
  • 對象:從它可以獲取異步操作的消息

特點

  • 對象的狀態不受外界影響
    Promise對象代表一個異步操作,有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和Rejected(已失敗)。只有異步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。
  • 一旦狀態改變,就不會再變,任何時候都可以得到這個結果
    Promise對象的狀態改變,只有兩種可能:從Pending變為Resolved和從Pending變為Rejected。

缺點

  • 無法取消Promise
    一旦新建它就會立即執行,無法中途取消
  • 如果不設置回調函數,Promise內部拋出的錯誤,不會反應到外部
  • 當處於Pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)

更多:

  • ES6 新增

2. CSS

2.1. CSS 選擇器

  • 類選擇器
  • 標簽選擇器
  • ID選擇器
  • 後代選擇器
  • 群組選擇器
  • 偽類選擇器(before/after)
  • 兄弟選擇器(+~)
  • 屬性選擇器等等

2.2. 盒子模型

  • 塊級盒子(block)
  • 行內盒子(inline-block)

相關屬性
margin、border、padding、content

註意

  • 只有普通文檔流中塊級盒子的垂直外邊距才會發生合並,而行內盒子、浮動盒子或絕對定位之間的外邊距不會合並
    根據規範,一個盒子如果沒有上補白(padding-top)和上邊框(border-top),那麽這個盒子的上邊距會和其內部文檔流中的第一個子元素的上邊距重疊
    為父元素增加一個border-top或者padding-top即可解決這個問題
  • box-sizing 屬性的設置會影響盒子width和height的計算

更多:

  • 垂直外邊距合並--CSS的Margin屬性:詳解margin屬性

2.3. 浮動布局

設置元素的 float 屬性,能使該元素脫離普通文檔流
如果子元素全部設置為浮動,則父元素是塌陷的

  • 清除浮動
    clear:both,
  • BFC
    浮動元素的父元素 + overflow:hidden 樣式
  • 行內盒子(inline-block)
  • table也可以實現同樣的效果。

2.4. 定位布局

脫離文檔流:position 值為 relative/absolute/fixed

  • relative
    相對定位,它以自己原來的位置進行偏移,偏移後,原來的空間不會被其他元素占用
  • absolute
    絕對定位,它以離自己最近的定位父容器作為參照進行偏移
    常用的方式就是設置父容器的poistion:relative
  • fixed
    固定定位,以瀏覽器窗口為參照物
    PC網頁底部懸停的banner一般都可以通過fixed定位來實現,但fixed屬性在移動端有兼容性問題,因此不推薦使用,可替代的方案是:絕對定位+內部滾動。

更多:

  • CSS 定位

2.5. 彈性布局

即Flex布局,定義了flex的容器一個可伸縮容器

  • 容器本身會根據容器中的元素動態設置自身大小
  • 當Flex容器被應用一個大小時(width和height),將會自動調整容器中的元素適應新大小
  • Flex容器也可以設置伸縮比例和固定寬度,還可以設置容器中元素的排列方向(橫向和縱向)和是否支持元素的自動換行
    容器的屬性
    • flex-direction屬性
    • flex-wrap屬性
    • flex-flow
    • justify-content屬性
    • align-items屬性
    • align-content屬性
      項目的屬性
    • order屬性
    • flex-grow屬性
    • flex-shrink屬性
    • flex-basis屬性
    • flex屬性
    • align-self屬性
  • 註意,設為Flex布局以後,子元素的float、clear和vertical-align屬性將失效。

更多: Flex 布局

2.6. CSS3 動畫

  • transition
    讓元素的CSS屬性值的變化在一段時間內平滑的過渡
    CSS3引入了transfrom屬性,它可以通過對元素進行 平移(translate)、旋轉(rotate)、放大縮小(scale)、傾斜(skew)
    等操作,來實現2D和3D變換效果
    transiton 還有一個結束事件 transitionEnd,該事件是在CSS完成過渡後觸發,如果過渡在完成之前被移除,則不會觸發transitionEnd
  • animation
    需要設置一個@keyframes,來定義元素以哪種形式進行變換
    然後再通過動畫函數讓這種變換平滑的進行,從而達到動畫效果
    • 動畫可以被設置為永久循環演示
    • animation-play-state:paused可以暫停動畫
    • animation-fill-mode:forwards 可以讓動畫完成後定格在最後一幀
    • 可以通過JS監聽animation的開始、結束和重復播放時的狀態,分別對應三個事件,即 animationStart、animationEnd、animationIteration
      註意,當播放次數設置為1時,不會觸發 animationIteration

對比

  • animation 設置動畫效果更靈活更豐富
  • transition 只能通過主動改變元素的css值才能觸發動畫效果,而animation一旦被應用,就開始執行動畫

2.7. BFC

BFC---Block Formatting Context

是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面元素

比如:內部滾動就是一個BFC,當一個父容器的overflow-y設置為auto時,並且子容器的長度大於父容器時,就會出現內部滾動,無論內部的元素怎麽滾動,都不會影響父容器以外的布局,這個父容器的渲染區域就叫BFC。

特點

  • 盒子們自所在的containing block頂部一個接一個垂直排列
  • 水平方向上撐滿整個寬度(除非內部盒子自己建立了新的BFC)
  • 兩個相鄰的BFC之間的距離由margin決定
  • 在同一個BFC內部,兩個垂直方向相鄰的塊級元素的margin會發生“塌陷”

觸發BFC
根元素或其它包含它的元素

  • float的值不為none
  • overflow的值不為visible
  • display的值為inline-block、table-cell、table-caption
  • position的值為absolute或fixed
  • flex boxes (元素的display: flex或inline-flex)

應用

  • 清除內部浮動
    對子元素設置浮動後,父元素會發生高度塌陷,也就是父元素的高度變為0。解決這個問題,只需要把把父元素變成一個BFC就行了。常用的辦法是給父元素設置overflow:hidden
  • 垂直margin合並
    屬於同一個BFC的兩個相鄰元素的margin會發生重疊 —— 創建 BFC
  • 創建自適應兩欄布局 —— 解決侵占浮動元素的問題

參考: CSS: 潛藏著的BFC

2.8. Sprite,Iconfont,@font-face

  • Sprite圖
    為了減少http請求的次數,一般會將常用的小圖標排到一個大圖中,頁面加載時只需請求一次網絡,在css中通過設置background-position來控制顯示所需要的小圖標
  • Iconfont
    即字體圖標,就是將常用的圖標轉化為字體資源存在文件中,通過在CSS中引用該字體文件,然後可以直接用控制字體的css屬性來設置圖標的樣式
    字體圖標的好處是節省網絡請求、其大小不受屏幕分辨率的影響,並且可以任意修改圖標的顏色
  • @font-face
    是CSS3中的一個模塊
    通過@font-face可以定義一種全新的字體,通過css屬性font-family來使用這個字體

3. HTML

3.1. BOM

Browser Object Model 瀏覽器對象模型

當一個瀏覽器頁面初始化時,會在內存創建一個全局的對象,用以描述當前窗口的屬性和狀態,這個全局對象被稱為瀏覽器對象模型,即BOM

BOM的核心對象就是window,window對象也是BOM的頂級對象,其中包含了瀏覽器的 6個核心模塊:

  • document
    • 即文檔對象,渲染引擎在解析HTML代碼時,會為每一個元素生成對應的DOM對象,由於元素之間有層級關系,因此整個HTML代碼解析完以後,會生成一個由不同節點組成的樹形結構,俗稱DOM樹
    • document用於描述DOM樹的狀態和屬性,並提供了很多操作DOM的API。
  • frames
    • HTML 子框架,即在瀏覽器裏嵌入另一個窗口
    • 父框架和子框架擁有獨立的作用域和上下文。
  • history
    • 以棧(FIFO)的形式保存著頁面被訪問的歷史記錄
    • 頁面前進即入棧,頁面返回即出棧。
  • location
    • 提供了當前窗口中加載的文檔相關信息以及一些導航功能
  • navigator
    • 用來描述瀏覽器本身,包括瀏覽器的名稱、版本、語言、系統平臺、用戶特性字符串等信息
  • screen
    • 提供了瀏覽器顯示屏幕的相關屬性,比如顯示屏幕的寬度和高度,可用寬度和高度。

3.2. DOM 系統

Document Object Model 文檔對象模型,是所有瀏覽器公共遵守的標準

  • DOM將HTML和XML文檔映射成一個由不同節點組成的樹型結構,俗稱DOM樹
  • 其核心對象是document,用於描述DOM樹的狀態和屬性,並提供對應的DOM操作API

3.3. 事件系統

事件是用戶與頁面交互的基礎,到目前為止,DOM事件從PC端的 鼠標事件(mouse) 發展到了 移動端的 觸摸事件(touch) 和
手勢事件(guesture),touch事件描述了手指在屏幕操作的每一個細節,guesture 則是描述多手指操作時更為復雜的情況

總結如下:

  • 第一根手指放下,觸發 touchstart,除此之外什麽都不會發生
  • 手指滑動時,觸發touchmove
  • 第二根手指放下,觸發 gesturestart
  • 觸發第二根手指的 touchstart
  • 立即觸發 gesturechange
  • 任意手指移動,持續觸發 gesturechange
  • 第二根手指彈起時,觸發 gestureend,以後將不會再觸發 gesturechange
  • 觸發第二根手指的 touchend
  • 觸發touchstart (多根手指在屏幕上,提起一根,會刷新一次全局touch)
  • 彈起第一根手指,觸發 touchend

DOM2.0 模型將事件處理流程分為三個階段,即 事件捕獲階段 、 事件處理階段 、 事件冒泡階段

  • 事件捕獲
    當用戶觸發點擊事件後,頂層對象document 就會發出一個事件流,從最外層的DOM節點向目標元素節點傳遞,最終到達目標元素。
  • 事件處理
    當到達目標元素之後,執行目標元素綁定的處理函數。如果沒有綁定監聽函數,則不做任何處理。
  • 事件冒泡
    事件流從目標元素開始,向最外層DOM節點傳遞,途中如果有節點綁定了事件處理函數,這些函數就會被執行。

利用事件冒泡原理可以實現 事件委托

所謂事件委托,就是在父元素上添加事件監聽器,用以監聽和處理子元素的事件,避免重復為子元素綁定相同的事件

  • 方式
    當目標元素的事件被觸發以後,這個事件就從目標元素開始,向最外層元素傳遞,最終冒泡到父元素上,父元素再通過event.target獲取到這個目標元素
  • 好處
    父元素只需綁定一個事件監聽,就可以對所有子元素的事件進行處理了,從而減少了不必要的事件綁定,對頁面性能有一定的提升。

更多: 事件委托和 this

3.4. HTML 解析過程

瀏覽器加載 html 文件以後,渲染引擎會從上往下,一步步來解析HTML標簽

過程如下:

  • 請求服務器返回HTML文件
    用戶輸入網址,瀏覽器向服務器發出請求,服務器返回html文件;
  • 生成dom 樹
    渲染引擎開始解析 html 標簽,並將標簽轉化為DOM節點,生成 DOM樹;
  • css文件請求
    如果head 標簽中引用了外部css文件,則發出css文件請求,服務器返回該文件,該過程會阻塞後面的解析;
  • js 請求
    如果引用了外部 js 文件,則發出 js 文件請求,服務器返回後立即執行該腳本,這個過程也會阻塞html的解析;
  • 生成渲染樹
    引擎開始解析 body 裏面的內容,如果標簽裏引用了css 樣式,就需要解析剛才下載好的css文件,然後用css來設置標簽的樣式屬性,並生成渲染樹;
  • 下載圖片資源
    如果 body 中的 img 標簽引用了圖片資源,則立即向服務器發出請求,此時引擎不會等待圖片下載完畢,而是繼續解析後面的標簽;
  • 重新渲染
    • 服務器返回圖片文件,由於圖片需要占用一定的空間,會影響到後面元素的排版,因此引擎需要重新渲染這部分內容;
    • 如果此時 js 腳本中運行了 style.display="none",布局被改變,引擎也需要重新渲染這部分代碼;
  • 直到 html 結束標簽為止,頁面解析完畢。

3.5. 重繪 和 回流

  • 回流
    當渲染樹中的一部分(或全部)因為元素的規模尺寸,布局,隱藏等改變而需要重新構建
    如上面的img文件加載完成後就會引起回流,每個頁面至少需要一次回流,就是在頁面第一次加載的時候
  • 重繪
    當渲染樹中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響布局的,比如 background-color

從上面可以看出,回流必將引起重繪,而重繪不一定會引起回流

會引起重繪和回流的操作如下:

  • 添加、刪除元素(回流+重繪)
  • 隱藏元素,display:none(回流+重繪),visibility:hidden(只重繪,不回流)
  • 移動元素,比如改變top,left的值,或者移動元素到另外一個父元素中。(重繪+回流)
  • 對style的操作(對不同的屬性操作,影響不一樣)
  • 還有一種是用戶的操作,比如改變瀏覽器大小,改變瀏覽器的字體大小等(回流+重繪)
  • 另外,transform操作不會引起重繪和回流,是一種高效率的渲染。這是因為transform屬於合成屬性,對合成屬性進行 transition/animation 動畫時將會創建一個合成層,這使得動畫元素在一個獨立的層中進行渲染,當元素的內容沒有發生改變,就沒必要進行重繪,瀏覽器會通過重新復合來創建動畫幀。

3.6. 本地存儲

避免取回數據前頁面空白,減少請求服務器次數

  • cookie
    • 本地存儲最原始的方式
      cookie 是存放在本地瀏覽器的一段文本,數據以鍵值對的形式保存,可以設置過期時間。
    • 不適合大量數據的存儲
      因為每請求一次頁面,cookie 都會發送給服務器,這使得 cookie速度很慢而且效率也不高。因此cookie的大小被限制為4k左右(不同瀏覽器可能不同,分HOST)
  • html5 提供了兩種在客戶端存儲數據的新方法:
    • localStorage
      永久存儲
    • sessionStorage
      存儲期限僅限於瀏覽器會話(session),即當瀏覽器窗口關閉後,sessionStorage中的數據被清除
    都是以key/value的形式來存儲數據
    localStorage的存儲空間大約5M左右(不同瀏覽器可能不同,分 HOST),這個相當於一個5M大小的前端數據庫,相比於cookie,可以節約帶寬,但localStorage在瀏覽器隱私模式下是不可讀取的,當存儲數據超過了 localStorage 的存儲空間後會拋出異常。
    此外,H5還提供了逆天的 websql 和 indexedDB,允許前端以關系型數據庫的方式來存儲本地數據

cookie作用是與服務器交互,作為HTTP規範的一部分,web storage僅僅為本地存儲而生

更多:常用的 web 客戶端存儲

3.7. 瀏覽器緩存機制

瀏覽器緩存機制是指通過 HTTP 協議頭裏的 Cache-Control (或 Expires) 和 Last-Modified (或 Etag) 等字段來控制文件緩存的機制。

  • Cache-Control
    • 用於控制文件在本地緩存有效時長
    • 比如服務器回包:Cache-Control:max-age=600
      表示文件在本地應該緩存,且有效時長是600秒 (從發出請求算起)。在接下來600秒內,如果有請求這個資源,瀏覽器不會發出 HTTP請求,而是直接使用本地緩存的文件。
  • Last-Modified
    • 標識文件在服務器上的最新更新時間
      下次請求時,如果文件緩存過期,瀏覽器通過 If-Modified-Since 字段帶上這個時間,發送給服務器,由服務器比較時間戳來判斷文件是否有修改。如果沒有修改,服務器返回304告訴瀏覽器繼續使用緩存;如果有修改,則返回200,同時返回最新的文件。
  • Cache-Control 通常與 Last-Modified 一起使用
    一個用於控制緩存有效時間,一個在緩存失效後,向服務查詢是否有更新。
    • Cache-Control 還有一個同功能的字段:Expires。Expires 的值為一個絕對的時間點
      如:Expires: Thu, 10 Nov 2015 08:45:11 GMT,表示在這個時間點之前,緩存都是有效的。
  • Etag 也是和 Last-Modified 一樣,對文件進行標識的字段
    不同的是,Etag 的取值是一個對文件進行標識的特征字串。在向服務器查詢文件是否有更新時,瀏覽器通過 If-None-Match
    字段把特征字串發送給服務器,由服務器和文件最新特征字串進行匹配,來判斷文件是否有更新。沒有更新回包304,有更新回包200。Etag 和 Last-Modified 可根據需求使用一個或兩個同時使用。兩個同時使用時,只要滿足基中一個條件,就認為文件沒有更新。

另外有兩種特殊的情況:

  • 手動刷新頁面(F5)
    瀏覽器會直接認為緩存已經過期(可能緩存還沒有過期),在請求中加上字段:Cache-Control:max-age=0,發包向服務器查詢是否有文件是否有更新。
  • 強制刷新頁面(Ctrl+F5)
    瀏覽器會直接忽略本地的緩存(有緩存也會認為本地沒有緩存),在請求中加上字段:Cache-Control:no-cache (或 Pragma:no-cache),發包向服務重新拉取文件

3.8. History

用戶訪問網頁的歷史記錄通常會被保存在一個類似於棧的對象中,即history對象,點擊返回就出棧,跳下一頁就入棧

它提供了以下方法來操作頁面的前進和後退:

  • window.history.back( ) 返回到上一個頁面
  • window.history.forward( ) 進入到下一個頁面
  • window.history.go( [delta] ) 跳轉到指定頁面

HTML5 對History Api 進行了增強,新增了兩個Api 和一個事件,分別是pushState、replaceState 和 onpopstate:

  • pushState是往history對象裏添加一個新的歷史記錄,即壓棧。
  • replaceState 是替換history對象中的當前歷史記錄。
  • 當點擊瀏覽器後退按鈕或 js調用history.back 都會觸發 onpopstate 事件。
    與其類似的還有一個事件:onhashchange,onhashchange是老API,瀏覽器支持度高,本來是用來監聽hash變化的,但可以被利用來做客戶端前進和後退事件的監聽,而onpopstate是專門用來監聽瀏覽器前進後退的,不僅可以支持hash,非hash的同源 url 也支持。

3.9. HTML5離線緩存

HTML5離線緩存又叫Application Cache,是從瀏覽器的緩存中分出來的一塊緩存區,如果要在這個緩存中保存數據,可以使用一個描述文件(manifest file),列出要下載和緩存的資源。

manifest 文件是簡單的文本文件,它告知瀏覽器被緩存的內容(以及不緩存的內容)。manifest 文件可分為三個部分:

  • CACHE MANIFEST - 在此標題下列出的文件將在首次下載後進行緩存
  • NETWORK - 在此標題下列出的文件需要與服務器的連接,且不會被緩存
  • FALLBACK - 在此標題下列出的文件規定當頁面無法訪問時的回退頁面(比如 404 頁面)

離線緩存為應用帶來三個優勢:

  • 離線瀏覽 - 用戶可在應用離線時使用它們
  • 速度 - 已緩存資源加載得更快
  • 減少服務器負載 - 瀏覽器將只從服務器下載更新過或更改過的資源。

參考:

  • javascript中的深拷貝和淺拷貝
  • web 前端知識體系精簡

前端基礎精簡總結