2012-03-20 50 views
14

在回答我的answer yesterday約旋轉圖像,Jamund告訴我使用.data()代替.attr()在.data或attr中保存對象狀態 - 性能與CSS?

首先,我認爲他是對的,但後來我想到了一個更大的背景下 ...它總是更好使用.data()而不是.attr()?我看了一些其他職位一樣what-is-better-data-or-attrjquery-data-vs-attrdata

的答案對我來說不理想......

所以我提出和通過edited the example加入CSS。我認爲在每個圖像上旋轉不同的風格可能很有用。我的風格是如下:

.rp[data-rotate="0"] { 
    border:10px solid #FF0000; 
} 
.rp[data-rotate="90"] { 
    border:10px solid #00FF00; 
} 
.rp[data-rotate="180"] { 
    border:10px solid #0000FF; 
} 
.rp[data-rotate="270"] { 
    border:10px solid #00FF00; 
} 

由於設計和編碼往往是分開的,它可能是一個不錯的功能在CSS來處理這個,而不是添加此功能爲JavaScript。同樣在我的情況下,data-rotate就像特殊狀態其中圖片當前有。所以在我看來,在DOM中表示它是有意義的。

我也認爲這可能是一種情況下,用.attr()然後用.data()保存更好。 從未在之前提到過的其中一篇文章中提到過。

但後來我想到了性能。哪個功能更快?我建立了自己的如下測試:

<!DOCTYPE HTML> 
<html> 
<head> 
<title>test</title> 
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> 
<script type="text/javascript"> 
function runfirst(dobj,dname){ 
    console.log("runfirst "+dname); 
    console.time(dname+"-attr"); 
    for(i=0;i<10000;i++){ 
    dobj.attr("data-test","a"+i); 
    } 
    console.timeEnd(dname+"-attr"); 
    console.time(dname+"-data"); 
    for(i=0;i<10000;i++){ 
    dobj.data("data-test","a"+i); 
    } 
    console.timeEnd(dname+"-data"); 
} 
function runlast(dobj,dname){ 
    console.log("runlast "+dname); 
    console.time(dname+"-data"); 
    for(i=0;i<10000;i++){ 
    dobj.data("data-test","a"+i); 
    } 
    console.timeEnd(dname+"-data"); 
    console.time(dname+"-attr"); 
    for(i=0;i<10000;i++){ 
    dobj.attr("data-test","a"+i); 
    } 
    console.timeEnd(dname+"-attr"); 
} 
$().ready(function() { 
    runfirst($("#rp4"),"#rp4"); 
    runfirst($("#rp3"),"#rp3"); 
    runlast($("#rp2"),"#rp2"); 
    runlast($("#rp1"),"#rp1"); 
}); 
</script> 
</head> 
<body> 
    <div id="rp1">Testdiv 1</div> 
    <div id="rp2" data-test="1">Testdiv 2</div> 
    <div id="rp3">Testdiv 3</div> 
    <div id="rp4" data-test="1">Testdiv 4</div> 
</body> 
</html> 

還應表明是否有預定義的data-test與否的差別。

一個結果是這樣的:

runfirst #rp4 
#rp4-attr: 515ms 
#rp4-data: 268ms 
runfirst #rp3 
#rp3-attr: 505ms 
#rp3-data: 264ms 
runlast #rp2 
#rp2-data: 260ms 
#rp2-attr: 521ms 
runlast #rp1 
#rp1-data: 284ms 
#rp1-attr: 525ms 

所以.attr()功能也總是需要更多的時間比.data()功能。這是我認爲的.data()的一個論據。因爲表演總是一個論點!

然後我想一些問題,在這裏發佈我的結果,並以書面的行爲我的問題堆棧溢出給我看(類似標題)

夠真相比,有一個interesting post about performance

我讀它並運行他們的例子。而現在我很困惑! 這個測試表明.data().attr()要慢!?!!爲什麼?

首先我認爲這是因爲一個不同的jQuery庫,所以我編輯它和saved the new one。但結果並沒有改變......

所以現在我的問題給你:

  • 爲何會出現在性能上在這兩個例子有哪些區別?
  • 如果表示狀態,您更喜歡使用數據HTML5屬性而不是數據嗎?雖然在編碼時不需要它?爲什麼 - 爲什麼不呢?

現在取決於性能:

  • 將表現爲你使用.attr()而不是數據,如果它表明.attr()更好是爭論?儘管數據旨在用於.data()

更新1:
我沒看到,沒有開銷.data()要快得多。誤解了數據:)但我對第二個問題更感興趣。 :)

如果 表示一個狀態,您更喜歡使用數據HTML5屬性而不是數據嗎?雖然編碼時不需要 編碼?爲什麼 - 爲什麼不呢?

是否還有其他某些原因可以使用.attr()而不是.data()?例如互操作性?因爲.data()是jQuery的風格和HTML屬性可以被所有讀取...

更新2:

正如我們在his answerattrT.J Crowderspeed test看到的是更快然後data!這又讓我困惑:)但請!表演是一種說法,但不是最高的!所以也請回答我的其他問題!

更新3:

我的測試,似乎是因爲fire-bug我以前在測試時是假的!同一個文件在鉻列出attr更快,第二個測試jsperf也說attr更快

+0

_「如果表明.attr()更好,那麼使用.attr()而不是數據的性能會成爲一個參數嗎?」_ **是...還有什麼可以作爲參數? ** – gdoron 2012-03-20 08:47:35

+0

其他可能是:更好的可調,更好的代碼,更好的可編輯性,更好的可理解性等... OOP編程的性能低於程序性能,但它往往更好:) – Neysor 2012-03-20 08:50:42

+4

*「因爲性能總是一個參數!」*不在2012年。讓我們來看看你的'runfirst#rp4'結果:'attr'的10k迭代需要515ms ;數據的10k次迭代需要268ms。這是51.5 usec(*微秒*,百萬分之一秒**)每個與每個26.8 usec。所以你想知道是否使用'data',如果它可以節省你24.7的usec。人類感知的東西只有十分之幾秒。所以對於它來說,重要的是,你必須在一個緊密的循環中操作大約4000次,以便讓人們注意到它們之間的差異。這甚至不值得擔心,即使在鼠標移動處理程序中也是如此。 :-) – 2012-03-20 08:51:40

回答

15

該性能部分問題尖叫的過早優化;見下文。 (爲了避免出現錯誤的想法:我也經常對有關同樣的過早優化問題感到疑惑。)

但是讓性能不受影響(其他要點在圖的下方):儘可能我可以看到,attr比jQuery 1.7中的data更快。1:http://jsperf.com/jquery-setting-attr-vs-data這讓我感到驚訝。並不是說這很可能很重要。

無償條形圖(更長的線=更快的性能):

Gratuitous bar graph from jsperf

是否有你能想到的一些其它原因,使用.attr(),而不是。數據()?

至少幾個浮現在腦海中:

  1. data的優點是,它並沒有寫入到每一次的元素;你只能第一次寫實際的元素,從那時開始,jQuery只是更新它在一個單獨的對象緩存中維護的JavaScript對象中的一個值(通過一個鍵連接到元素)。 (我不知道爲什麼它比attr慢,也許是因爲間接的。)

  2. 有一件事我不喜歡data的是,它不是對稱的:當你第一次一個元素訪問data,該數據對象被從元素中接收到data-*屬性;但從那裏開始,兩者之間沒有任何關係。

    實施例(live copy | live source):

    var target = $("#target"); 
    display("data('foo'): " + target.data("foo")); 
    display("data-foo: " + target.attr("data-foo")); 
    display("Setting data('foo')"); 
    target.data("foo", "updated data('foo')"); 
    display("data('foo'): " + target.data("foo")); 
    display("data-foo: " + target.attr("data-foo")); 
    display("Setting data-foo"); 
    target.attr("data-foo", "updated data-foo"); 
    display("data('foo'): " + target.data("foo")); 
    display("data-foo: " + target.attr("data-foo")); 
    

    假設#target元件開始不與data-foo="bar",輸出爲:

    data('foo'): bar 
    data-foo: bar 
    Setting data('foo') 
    data('foo'): updated data('foo') 
    data-foo: bar 
    Setting data-foo 
    data('foo'): updated data('foo') 
    data-foo: updated data-foo

    即可以是混亂和令人驚訝的。您必須考慮的方式是data-*屬性僅爲默認值。我只是不喜歡他們如何依賴你是否曾經打過data;除非你從不直接寫data-*屬性,你不能確定data會得到什麼值(原始值來自標記,或者是在你調用data之前稍後更新的值)。這對我來說似乎有點混亂,但是如果你設置了自己的規則(例如,不要直接寫入data-*屬性,並且只使用data),那麼可以避免混亂。

  3. 當您使用attr時,只能存儲字符串。當您使用data時,您可以存儲任何JavaScript值或對象引用。


由於性能始終是一個說法!

不在2012年。:-)或者至少,它比其他參數低很多,比以前缺少一個明確的,可證明的性能問題。

讓我們來看看你的runfirst #rp4結果:attr的10k迭代需要515ms; data的10k迭代需要268ms。那是51。5 usec(微秒,百萬分之一秒)每個對26.8個使用者。所以你想知道是否使用data,如果它可以節省每次操作24.7次使用。人類感知的東西只有十分之幾秒。所以對於它來說,重要的是,你必須在一個緊密的循環中操作大約4000次,以便讓人們注意到它們之間的差異。這甚至不值得擔心,即使在mousemove處理程序中。

如果你進入這種領域(緊湊環路中每秒4000個),你可能想避免在元素上存儲信息。

+0

謝謝你,我喜歡你的評論如下。但我編輯了我的帖子,因爲我確實非常關注性能,但是我在其他問題上真的更有興趣:) – Neysor 2012-03-20 09:04:02

+0

@Neysor:剛纔看到了編輯和編輯。 :-) – 2012-03-20 09:18:06

+0

我讀過它並感謝你的第二個參數。我不知道他們預裝了'data- *'。第三個參數對我來說很清楚,並且經常用到:) 但是因爲我真的想知道它:你會在類似的情況下使用'attr()',例如[我給你展示](http://jsfiddle.net/vYB5r/ 4 /),但在編程時不使用。僅僅因爲你有一種感覺,設計師有時可能需要它?或者你會總是使用'.data()',如果請求來了,你會改變它... – Neysor 2012-03-20 09:34:36

0

您可以使用jQuery.data。它幾乎總是最快的。 jQuery試圖在每個瀏覽器上優化其功能,並最大限度地提高可兼容性。因此,對於新版本的jQuery,您可能會獲得此功能的性能。 This 2nd test給了我jQuery.data作爲勝利者。

+0

是的,我明白了。但我沒有把我的觀點弄清楚。抱歉!但我的意思是,表演是一個論點,但不是最高的。其他原因也應該進行比較。那麼你對我的其他問題有什麼意見? (見更新1) – Neysor 2012-03-20 09:12:59

1

鑑於.data()確實慢.attr()on most browsers,但速度差異並不重要,這個問題的data()超過attr()一個優勢是,數據會自動強制data-屬性numbersboolean值是否匹配。

這意味着,

<div id="boolean" data-t="true" data-f="false"> 

將導致true & false布爾運行時間值,當您運行此:

console.log($('#boolean').data('t')); // reports true (not a string) 
console.log($('#boolean').data('f')); // reports false (not a string) 

<div id="number" data-n="123.456"> 

會導致一些運行值爲123.456當您運行此:在另一方面

console.log($('#number').data('n')); // Reports 123.456 (not a string) 

attr僅僅處理字符串的工作,但將值轉換爲字符串保存。當你抓取它們時它不會強制取值。

attrdata之間的選擇取決於你需要一個具體的例子如下特徵:

  • 我在哪裏注入從服務器到頁data-設置,我傾向於使用data()訪問這些網站,如果僅僅是因爲它代碼較短。
  • 如果我需要數據在DOM中可見,我將使用attr()來保存值。