第十七課:js數據緩存系統的原理

這一章主要講的是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就能夠了。很是方便。可是兼容性就不容樂觀了。

這是新技術,瞭解就行。

 

總結:

數據緩存其實就是在目標元素與緩存體之間創建一對一的關係,而後在緩存體上操做數據。

 

 

 

加油!

相關文章
相關標籤/搜索