有趣的jquery.data

剛在看jquery.data方法這個方法,其官網http://api.jquery.com/jQuery.data/上對其有多種不一樣的評價,有考慮$.data的速度和el.data的速度誰更快的,有考慮.data能夠存儲多少數據的,有考慮是否垃圾回收器能夠回收這些.data的數據等等。

關於$.data()和el.data()速度的說法在http://jsperf.com/jquery-data-vs-jqueryselection-data這個網頁上有一個模擬測試,經過多次的測試$.data()的速度幾乎是el.data()的3倍。而且在其下面的一大堆的環境和瀏覽器中悲催的發現$.data()和el.data()的速度之差不是一點點。之前用data方法都是使用el.data(),因爲它的意思更加的明確,更容易明白我們在幹什麼。看來今後還是得走規範道路了,在官網只看到了$.data()的介紹,所以以後還是用$.data()吧。

關於.data的內存回收問題,網上是有很多這個問題的內存泄露的文章,在jquery forum的http://forum.jquery.com/topic/data-object-and-memory-leak中有這樣一段話:

the current $.data implementation is optimized for host objects only, and not for native objects too.
In fact, it uses a cache object to store all related data and an expando with numerical values to keep references.
The need of such solution is unquestionable and it fits well because elements are normally "eliminated" by using .remove() that also cleans respective data. Native objects, in other hand, are not "eliminated" with such call, and related data exists until the window is closed.

Of course, this problem also exists with the event API, that uses data API to store handlers...

中文爲:$.data()方法應用到宿主對象上,運行會得到優化,但在本地對象上使用該方法,結果未必盡如人意。一個元素在正常情況下可以使用.remove()方法將其刪除,並將各自的數據清除。但對於本地對象而言,這是不能徹底刪除的,這些相關的數據一直持續到窗口對象關閉。同樣這些問題也出現在event對象上,因爲事件處理器(handlers)也使用該方法來存儲的。

robert.katic對.data()方法進行了重寫,並且增加了.removeData()方法:

(function($){ 
    var expando = "jQuery" + (new Date).getTime(), 
        hasOwnProperty = Object.prototype.hasOwnProperty, 
        _data = $.data, 
        _removeData = $.removeData; 
    $.data = function( obj, name, data ) { 
        if ( obj.nodeType ) { 
            return _data( obj, name, data ); 
        } 
        var thisCache, hasCache = hasOwnProperty.call( obj, expando ); 
        if ( !hasCache && typeof name === "string" && data === undefined ) { 
            return undefined; 
        } 
  
        if ( typeof name === "object" ) { 
            obj[ expando ] = $.extend(true, {}, name); 
  
       } else if ( !hasCache ) { 
            obj[ expando ] = {}; 
        } 
        thisCache = obj[ expando ]; 
        if ( typeof name === "string" ) { 
            if ( data !== undefined ) { 
                thisCache[ name ] = data; 
            } 
            return thisCache[ name ]; 
        } 
        return thisCache; 
    }; 
  
    $.removeData = function( obj, name ) { 
        if ( obj.nodeType ) { 
            return _removeData( obj, name ); 
        } 
        if ( name ) { 
            if ( hasOwnProperty.call( obj, expando ) ) { 
                delete obj[ expando ][ name ]; 
                if ( $.isEmptyObject( obj[expando] ) ) { 
                    delete obj[ expando ]; 
                } 
            } 
        } else { 
            delete obj[ expando ]; 
        } 
    }; 
})(jQuery);
這樣就可以不用擔心.data()的內存泄露問題了。

可是一個有趣的問題出現了,在http://news.ycombinator.com/item?id=3367510上在250天前說:don't use the jquery .data() method,use .attr() instead。我奇了怪了,繼續往下看,原來這是一個bug,我試驗了一下其中的例子,也沒發現什麼奇怪的東西出現。在http://jsfiddle.net/4bd23/上實驗,果然有問題,在自己的瀏覽器上測試也有問題。還發現.data()還可以使用<div id="foo" data-myinline="1.410"></div>​這樣的方式來設值,用foo.data('myinline')就可以獲得值了。

有這樣的有趣的問題出現,以後使用.data()還是得多加小心。好了,準備睡覺。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章