亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

淺析jQuery 3.0中的Data

2019-11-20 09:42:33
字體:
來源:轉載
供稿:網友

jQuery 3.0 在6月9日正式發布了,3.0 也被稱為下一代的 jQuery。這個版本從14年10月開始,其中發布過一次beta 版(2016/1/14,)和候選版(2016/05/20)。一路走來,頗為不易。

一、Data淺析

jQuery 3.0 中的 Data 是內部使用的,定義為一個“類”。一共用它創建了兩個對象,dataPriv 和 dataUser。Data 有 1 個對象屬性(expando)和類屬性(uid),有 6 個方法,如下

下面分別解讀

1、Data.uid

這是一個從 1 開始用來自增的數字。

2、expando

由 jQuery.expando 和 uid 組合而成,它用來作為元素(如DOM元素)的key,是唯一的。jQuery.expando 的生成如下

jQuery.expando = "jQuery" + ( version + Math.random() ).replace( //D/g, "" )

即 'jQuery' + (版本號 + 隨機數),然后把非數字的都去掉,比如

"jQuery" + ".." + . == "jQuery..." 

去掉非數字變為

jQuery30009423638425146147"

jQuery 3.0 內部變量 dataPriv 和 dataUser 生成 expando 如下

jQuery 300 024727210109188635 1jQuery 300 024727210109188635 2

第三部分是隨機數,每次刷新都會變,其它部分的不變。

3、cache

cache 方法會給 owner 上綁定一個對象作為存儲,owner 必須滿足 acceptData 的,cache 會以 this.expando 為線索 key。
owner 有兩種,一中是DOM元素(nodeType為1和9),另一種則是普通的JS對象。諸如 文本節點(nodeType=3)、注釋節點(nodeType=8) 一律不添加。

acceptData 的定義如下

var acceptData = function( owner ) {  // Accepts only:  // - Node  //  - Node.ELEMENT_NODE  //  - Node.DOCUMENT_NODE  // - Object  //  - Any  /* jshint -W018 */  return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );};

acceptData 在 3.0 中一共有 3 處使用,分別為

Data 類的 cache 方法,為私有方法不提供給程序員使用。$.cleanData 方法,清空元素關聯的所有緩存數據。為公開方法,但很少使用。該方法被用在 empty、html、replaceWith、remove 方法中。$().trigger 方法,主動派發事件,為公開方法。

如果是 DOM 元素,則直接使用點操作符賦值,如果是普通 JS 對象則使用 ES5 的 Object.defineProperty 方法,這也是 jQuery 3.0 會使用新 API 的體現。

// If it is a node unlikely to be stringify-ed or looped over// use plain assignmentif ( owner.nodeType ) {  owner[ this.expando ] = value;// Otherwise secure it in a non-enumerable property// configurable must be true to allow the property to be// deleted when data is removed} else {  Object.defineProperty( owner, this.expando, {    value: value,    configurable: true  } );}

轉換成如下代碼

elem['jQuery3000247272101091886351'] = dataObj;var person = {name: 'John', age: 30};Object.defineProperty( person, 'jQuery3000247272101091886351', {  value: dataObj,  configurable: true} );

cache 方法就是這樣,傳入 owner,只有第一次會 set ,返回 value (一個空對象),之后取到 value 后直接返回。

源碼

cache: function( owner ) {  // Check if the owner object already has a cache  var value = owner[ this.expando ];  // If not, create one  if ( !value ) {    value = {};    // We can accept data for non-element nodes in modern browsers,    // but we should not, see #8335.    // Always return an empty object.    if ( acceptData( owner ) ) {      // If it is a node unlikely to be stringify-ed or looped over      // use plain assignment      if ( owner.nodeType ) {        owner[ this.expando ] = value;      // Otherwise secure it in a non-enumerable property      // configurable must be true to allow the property to be      // deleted when data is removed      } else {        Object.defineProperty( owner, this.expando, {          value: value,          configurable: true        } );      }    }  }  return value;},

4、set

上面的 cache 方法為 owner 建立一個以 expando 為 key 的空對象,后面所有的方法都圍繞這個空對象來展開,這個空對象就被稱為緩存對象,后面所有的數據都添加到它上面。set 就是給這個對象來添磚加瓦,set 每次都是先取回 cache ,再給其添加新的屬性及數據。如果 data 是字符串,則以它為 key 添加,如果是對象,則遍歷它添加。只需注意一點,橫線連接符內部會被轉成駝峰格式,這也是為了對 H5 data-xxx 的兼容 。

源碼

set: function( owner, data, value ) {  var prop,    cache = this.cache( owner );  // Handle: [ owner, key, value ] args  // Always use camelCase key (gh-2257)  if ( typeof data === "string" ) {    cache[ jQuery.camelCase( data ) ] = value;  // Handle: [ owner, { properties } ] args  } else {    // Copy the properties one-by-one to the cache object    for ( prop in data ) {      cache[ jQuery.camelCase( prop ) ] = data[ prop ];    }  }  return cache;},

5、get

get 簡單至極,傳 key 則從 cache 上取回該 key 的值,無則取回整個 cache。

源碼

get: function( owner, key ) {  return key === undefined ?    this.cache( owner ) :    // Always use camelCase key (gh-2257)    owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];},

6、access

這個方法即時 getter,也是 setter,如此而已。

getter 條件

key 是 undefined,這時取整個 cachekey 是字符串且value 是undefined,這是取指定 key 的值

setter 條件

owner、key、value 這三個參數都傳

源碼

access: function( owner, key, value ) {  // In cases where either:  //  //  1. No key was specified  //  2. A string key was specified, but no value provided  //  // Take the "read" path and allow the get method to determine  // which value to return, respectively either:  //  //  1. The entire cache object  //  2. The data stored at the key  //  if ( key === undefined ||      ( ( key && typeof key === "string" ) && value === undefined ) ) {    return this.get( owner, key );  }  // When the key is not a string, or both a key and value  // are specified, set or extend (existing objects) with either:  //  //  1. An object of properties  //  2. A key and value  //  this.set( owner, key, value );  // Since the "set" path can have two possible entry points  // return the expected data based on which path was taken[*]  return value !== undefined ? value : key;},

7、remove

清空綁定元素(owner)上面的緩存對象,依然需要先通過 this.expando 拿到 cache,如果傳了 key 則刪除指定key的值(key自身也被刪除)。
當然 jQuery API 保持已有的方便性,key 可以為一個數組,這樣可以批量刪除多個 key。如果 key 沒傳則將整個 cache 刪除,這里區分了 DOM 和普通 JS 對象,DOM 對象使用undefined賦值,JS 對象則使用 delete。

源碼

remove: function( owner, key ) {  var i,    cache = owner[ this.expando ];  if ( cache === undefined ) {    return;  }  if ( key !== undefined ) {    // Support array or space separated string of keys    if ( jQuery.isArray( key ) ) {      // If key is an array of keys...      // We always set camelCase keys, so remove that.      key = key.map( jQuery.camelCase );    } else {      key = jQuery.camelCase( key );      // If a key with the spaces exists, use it.      // Otherwise, create an array by matching non-whitespace      key = key in cache ?        [ key ] :        ( key.match( rnotwhite ) || [] );    }    i = key.length;    while ( i-- ) {      delete cache[ key[ i ] ];    }  }  // Remove the expando if there's no more data  if ( key === undefined || jQuery.isEmptyObject( cache ) ) {    // Support: Chrome <=35 - 45    // Webkit & Blink performance suffers when deleting properties    // from DOM nodes, so set to undefined instead    // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)    if ( owner.nodeType ) {      owner[ this.expando ] = undefined;    } else {      delete owner[ this.expando ];    }  }}, 

8、hasData

用來判斷 owner 上是否有緩存數據,返回 true 或 false。

源碼

hasData: function( owner ) {  var cache = owner[ this.expando ];  return cache !== undefined && !jQuery.isEmptyObject( cache );}

二、Data在jQuery內部的使用

以上解讀完了 Data 的所有方法,上面也提到 Data 類是在 jQuery 內部使用的,一共創建了它的兩個對象:dataPriv 和 dataUser。

這兩個對象在 3.0.0 中有著明確的分工,dataPriv 可以猜測到是 “data” 和 “private” 兩個單詞的組合后簡寫。即 dataPriv 是私有的用來服務 jQuery 內部方法,dataUser 用來服務那些公開給用戶使用的方法。

下面看下這兩個對象分布在哪些模塊中使用。

完整版點擊展開可查看

dataPriv  公共    $.hasData    $.cleanData    cloneCopyEvent  隊列    $().queue    $()._queueHooks    $().promise  動畫    $().animate    $().stop    $().finish    showHide  事件    $.event.add    $.event.remove    $.event.dispatch    $.event.trigger  其它    setGlobalEval    domManip    defaultPrefilter    $().toggleClassdataUser  公共    $.hasData    $.cleanData    cloneCopyEvent  數據緩存    $.data    $.removeData    $().data    $().removeData  其它    dataAttr

以上可以看到,除了“公共”,DataPriv 用在了 jQuery 的 隊列、動畫、事件等模塊;dataUser 用在了數據緩存及dataAttr模塊。

“公共” 是指這三個方法內都用到了 dataPriv 和 dataUser

$.hasData(elem)

用來判斷 elem 上是否綁定了相關的數據緩存,返回 true 和false,只有 dataPriv 和 dataUser 上都沒有才返回 false

源碼

hasData: function( elem ) {return dataUser.hasData( elem ) || dataPriv.hasData( elem );},

$.cleanData(elems)

清空 elem 上綁定的所有數據緩存,理所當然的需要同時清空 dataPriv 和 dataUser 上的。
注意:雖然這個方法在公開暴露在了 $ 上, 但官網API上卻沒有該方法的介紹。另使用不當會造成嚴重后果,比如綁定了事件后(.on),調用該方法,綁定的事件將全部失效。因為會清空 dataPriv 內的所有數據。

cloneCopyEvent(src, dest)

這是一個內部方法,$.clone 會使用到它??寺≡貢r除了會克隆node節點外,綁定在node上的數據也會被克隆過去。比如

var cloneNode = $.clone(elem);

把 elem 克隆給 cloneNode,此時 elem 上添加的事件 cloneNode 上也會有。

三、1.x.x 和 2.x.x 的比較

jQuery 1.x 系列 和 2.x 系列的版本對 數據緩存模塊的實現差異還是很大的。大家可以對比我11年的這篇文章

1. 緩存的數據結構

1.x (直到1.11.2) 緩存都是存儲在 jQuery.cache 上的,2.x(包括3.x) 則使用了一個內部類 Data 做緩存,其主要用到了兩個對象 dataPriv 和 dataUser。很明顯 2.x 做的更好,它所有的緩存數據都是私有的,不會存在被誤寫的風險,而 1.x 的 jQuery.cache 是公開的,如果被誤寫(比如某個同學想當然的給$上添加一個cache對象)后果不堪設想。

2. jQuery._data

看到這個下劃線就知道是私有的(約定式),在 1.x 中是僅在內部使用的,不提供給開發者。以 1.11.2 示例、這個方法被事件模塊、隊列模塊、動畫模塊、setGlobalEval、cloneCopyEvent、fixCloneNodeIssues、domManip、showHide、defaultPrefilter、toggleClass 使用。3.x 則使用 dataPriv 和 dataUser 替代,大家可以對比看看。

(2/3).x 相比 1.x 明顯更優,dataPriv 和 dataUser 是真正的私有的(封裝的更好,更安全),比起 1.x 約定式的私有 jQuery._data。雖然 3.0.0 還保守的兼容了 jQuery._data,相信過不了多久的后續版本就會剔除。


3. 重構

1.x 以 $._data 為中心,以它來輔助實現其它 API, (2/3).x 以 dataPriv/dataUser 為中心來實現。(2/3).x 將代碼重構后提取出了 Data 類,更加清晰。

以上所述是小編給大家介紹的jQuery 3.0中的Data的全部敘述,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久久久网站| 最新69国产成人精品视频免费| 欧美日韩中国免费专区在线看| 美女福利视频一区| 在线丨暗呦小u女国产精品| 欧美视频一区二区三区…| 欧美裸体xxxxx| 欧美色图在线视频| 中文字幕欧美专区| 国产精品爽爽ⅴa在线观看| 亚洲缚视频在线观看| 欧美日韩裸体免费视频| 亚洲午夜久久久久久久| 精品久久中文字幕| 亚洲毛茸茸少妇高潮呻吟| 国产精品看片资源| 成人97在线观看视频| 亚洲最大激情中文字幕| 91高潮精品免费porn| 成人国产精品日本在线| 久久综合免费视频影院| 久久久亚洲影院你懂的| 91视频国产高清| 国产精品www色诱视频| 久久久国产影院| 欧美综合国产精品久久丁香| 7777精品久久久久久| 久久av红桃一区二区小说| 欧美丰满老妇厨房牲生活| 欧美激情视频网址| 91精品国产高清自在线| 国产欧美日韩精品专区| 国产精品∨欧美精品v日韩精品| 久久偷看各类女兵18女厕嘘嘘| 欧美麻豆久久久久久中文| 亚洲精品一区二区网址| 欧美韩国理论所午夜片917电影| 久久精品美女视频网站| 亚洲欧美国产高清va在线播| 亚洲va欧美va在线观看| 91精品视频免费观看| 亚洲第一福利网站| 九色成人免费视频| 亚洲欧美国产精品va在线观看| 亚洲欧美制服中文字幕| 国产精品旅馆在线| 国产欧美精品一区二区三区介绍| 成人久久精品视频| 国产亚洲激情在线| 国产日韩在线亚洲字幕中文| 97精品一区二区三区| 亚洲精品视频久久| 日韩精品一二三四区| 欧美日产国产成人免费图片| 欧美日韩亚洲系列| 一区三区二区视频| 91性高湖久久久久久久久_久久99| 成人亚洲综合色就1024| 992tv成人免费影院| 亚洲激情视频网| 精品久久久久久久久久| 亚洲跨种族黑人xxx| 久久人91精品久久久久久不卡| 国产精品毛片a∨一区二区三区|国| 日韩精品中文在线观看| 成人免费在线网址| 欧美精品做受xxx性少妇| 国产在线一区二区三区| 久久精品久久久久久国产 免费| 秋霞av国产精品一区| 中日韩美女免费视频网址在线观看| 亚洲第一av网站| 国产精品嫩草影院一区二区| 国产精品网红福利| 成人黄色免费片| 亚洲视频在线观看免费| 亚洲高清久久久久久| 国产婷婷97碰碰久久人人蜜臀| 色偷偷av亚洲男人的天堂| 国产精品久久久久久中文字| 91九色蝌蚪国产| 成人国产精品一区| 久久久91精品国产| 欧美一二三视频| 国产成人精品久久二区二区| 亚洲性日韩精品一区二区| 亚洲综合中文字幕在线| 国产69精品久久久久9999| 日韩高清中文字幕| 日韩精品免费电影| 亚洲精品国产精品乱码不99按摩| 亚洲精品国产福利| 亚洲国产女人aaa毛片在线| 国产亚洲欧美一区| 国产精品久久久久久av福利软件| 中文字幕欧美国内| 亚洲国产成人91精品| 欧美亚州一区二区三区| 欧美成人久久久| 上原亚衣av一区二区三区| 亚洲精品动漫100p| 国产在线精品播放| 国产精品第8页| 97福利一区二区| 国产精品av在线播放| 中文字幕亚洲激情| 精品国产福利视频| 国色天香2019中文字幕在线观看| 久久全球大尺度高清视频| 蜜臀久久99精品久久久无需会员| 亚洲人成电影网站色www| 国产精品久久久久久网站| 日韩中文字幕精品| 精品亚洲男同gayvideo网站| 美女黄色丝袜一区| 亚洲日本成人网| 久久天天躁狠狠躁夜夜爽蜜月| 国产成人自拍视频在线观看| 亚洲va久久久噜噜噜| 亚洲免费av电影| 亚洲一区免费网站| 91美女片黄在线观| 亚洲国产精品一区二区久| 欧美有码在线观看| 亚洲aⅴ日韩av电影在线观看| 久久天天躁狠狠躁夜夜躁2014| 亚洲黄色在线观看| 精品久久久久久久久国产字幕| 欧美性理论片在线观看片免费| 亚洲国产天堂久久综合| 亚洲深夜福利网站| 欧美黄色三级网站| 久久久久久久久久久人体| 国产精品久久久久久av福利| 国内精品久久久久影院 日本资源| 北条麻妃一区二区在线观看| 国产成人精品免高潮在线观看| 久久99精品久久久久久青青91| 91精品在线观| 亚洲激情在线视频| 欧美裸体视频网站| 久久青草福利网站| 欧美美女18p| 第一福利永久视频精品| 5566日本婷婷色中文字幕97| 久久久精品视频在线观看| 韩国三级日本三级少妇99| 亚洲国内高清视频| 日韩视频在线免费观看| 国产极品精品在线观看| 欧美刺激性大交免费视频| 色无极亚洲影院| 2021久久精品国产99国产精品| 日韩av电影国产| 欧美成人激情在线| 久久中文字幕在线视频| 午夜精品久久久久久久久久久久久| 成人免费大片黄在线播放| 亚洲成人在线网| 欧美午夜精品伦理| 国产精品一区二区三区在线播放| 欧美日韩日本国产| 尤物精品国产第一福利三区| 精品亚洲精品福利线在观看|