第十七课: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就能够了。很是方便。可是兼容性就不容乐观了。

这是新技术,了解就行。

 

总结:

数据缓存其实就是在目标元素与缓存体之间创建一对一的关系,而后在缓存体上操做数据。

 

 

 

加油!

相关文章
相关标签/搜索