有趣的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()还是得多加小心。好了,准备睡觉。

你可能感兴趣的:(jquery,function,浏览器,object,String,delete)