這一章主要講的是jQuery的緩存系統的歷史發展,以及他本身的框架的緩存系統的實現。都是源碼解析。瀏覽器
我就挑幾個重點講下:緩存
(1)jQuery的緩存機制的原理app
jQuery的緩存機制實現的原理是在元素中添加自定義屬性,而後把這個自定義屬性賦值爲uid,而這個uid就在jQuery的cache對象中的一個屬性(惟一的),這個惟一的屬性實際上是一個對象,這個對象裏面存儲的就是你給這個元素添加的數據。框架
舉個例子:ui
<input id="chaojidan" name="chaojidan" >spa
<input id="chaojidan1" name="chaojidan1" >設計
$("#chaojidan").data({name:"chaojidan",age:"25"});對象
執行這個語句後,接口
<input id="chaojidan" name="chaojidan" 自定義屬性(jQuery版本+隨機數) = uid(1,一個從0開始累加的整數)>ip
在jQuery中,$.cache = {1: { name:"chaojidan",age:"25" }}
當給第二個input添加數據時,
$("#chaojidan1").data({name:"chaojidan1",age:"26"});
執行這個語句後,
<input id="chaojidan1" name="chaojidan1" 自定義屬性(jQuery版本+隨機數) = uid(2,一個從0開始累加的整數)>
在jQuery中,$.cache = { 1: { name:"chaojidan",age:"25" }, 2: { name:"chaojidan1",age:"26" }}
取數據時,會先在元素中查找自定義屬性的值(uid),而後再去$.cache對象中查找uid,獲得以前存儲的數據,最後經過須要取得什麼數據的key值,返回value值。
(2)兼容性問題
在舊版本IE中,元素節點(object,embed,applet)只是COM的包裝,一旦引入資源後,它就會變成那種資源的實例。一旦這資源是由VB等語言編寫,因爲VM有嚴格的訪問控制,不能隨便給對象添加新屬性和方法,就會出現沒法使用jQuery緩存系統。
HTML5新增了一種data-*的緩存機制,當用戶在元素上設置了data-開頭的屬性時,它們的值會保存在元素節點的dataset對象上。可是它只支持字符串(以防循環引用)。
這裏我說下循環引用的實例:
input.moneySet = { fangzi:"shenzhen",ele:input}
元素節點input有一個自定義屬性是moneySet,它的值是一個對象,若是是一個字符串,永遠都不會循環引用。因爲是一個對象,對象中有一個ele屬性,這個屬性恰好又指向input元素。這時就出現了循環引用的狀態。
(3)新一代的jQuery緩存機制實現原理
它是經過對valueOf方法重寫,並經過Object.defineProperty方法操做實現的,這套緩存系統不支持IE8以及如下版本瀏覽器。
實現原理:對每個實例(調用jQuery緩存系統中data方法的任何東西),調用valueOf方法,並傳入jQuery中的Data類,若是返回object,就證實valueOf方法沒重寫,咱們就經過Object.defineProperty重寫它的valueOf方法。若是返回string,則已經被重寫了,就不用再次重寫。
Object.defineProperty(目標對象,要定義的屬性或者方法名,目標屬性所擁有的特性)
Object.defineProperty(目標對象,"valueOf",{ value:function(){ return value1} //writable ,configurable, enumerable內部屬性 ),這句代碼的意思就是,目標元素的valueOf方法被重寫了,它的valueOf方法的值是value1,同時還能夠設置valueOf是否能夠被遍歷,被重寫,被從新定義。默認狀況下是不能的。若是你在裏面寫了writable:true,那麼目標對象的valueOf就是可重寫的。
以上方法,還有內部屬性,在js高級程序設計裏面有詳解。可是實際項目中用的比較少,做爲了解就行。若是是開發移動端,仍是推薦去精讀的。
(4)ECMAScript6新特性建立的緩存系統
以前的緩存系統都是經過惟一的一個ID,來創建目標對象(元素節點)與緩存體(緩存系統Cache)之間的鏈接。而ES6中有一個新的集合對象WeakMap。
WeakMap是個什麼樣的對象呢,平時,咱們的js對象,鍵名name只能是字符串,鍵值key任意。咱們能夠經過for in循環遍歷它的全部鍵值對。而WeakMap的鍵名name只能爲一個非null的對象,鍵值key任意。咱們沒法經過for in循環遍歷它裏面的鍵值對,讀寫或刪除只能對它暴露的接口進行。它目前只有四個方法:set,get,has,delete。
舉個例子:
var map = new WeakMap();
el = document.body;
map.set(el,{data:{}}); //設置鍵值對
var value = map.get(el); //讀取目標值
console.log(value) //{data:{}}
console.log(map.has(el)) //是否有此鍵名name,這裏是true
map.delete(el) //刪除鍵值對。若是做爲鍵名的對象el被刪除,那麼它對應的緩存體(el:{data:{}})會自動被清除出WeakMap對象。
所以經過此對象很容易實現緩存系統。你們都知道,咱們的目標元素不過是元素節點,document對象,window對象,徹底能夠作爲WeakMap的鍵名。咱們能夠把緩存倉庫改爲一個WeakMap實例。咱們再也不須要用惟一的id來做爲橋樑關聯二者。只須要map.set方法就能夠創建關聯了。斷定目標元素是否關聯着緩存體,只須要用map.has方法。刪除緩存體用map.delete就能夠了。很是方便。可是兼容性就不容樂觀了。
這是新技術,瞭解就行。
總結:
數據緩存其實就是在目標元素與緩存體之間創建一對一的關係,而後在緩存體上操做數據。
加油!