2009-10-07 125 views
3

我發佈了另一個question在一個非常相似的話題,但結果是有點主觀。我能夠劃分問題的兩個問題,一個是我會在下面解釋:不使用jquery函數會對性能產生什麼影響?

下面的代碼:

<script type="text/javascript"> 
$(function() 
{ 
    $("#accordion").accordion(); 
    $("#datepicker").datepicker(); 
    $("#button").click(function() 
    { 
    runEffect(); 
    return false; 
    }); 
}); 
</script> 

問:如果我有這樣的代碼中調用的1000頁,但只有250頁面有一個日期選擇器ID。瀏覽器會花費額外的時間在試圖解析ID datepicker的其他750頁上,或者Jquery有一個明智的方法來解決這種情況而不影響性能?

如果代碼引用當前頁面的html標記中不存在的id或類,會發生什麼情況會影響性能?

+0

不錯,一直都在想這個! – Colin 2009-10-07 03:28:34

回答

7

對於那些說「不要擔心」的人,我無法反駁更多。

我建立這樣一個網站一旦在外部JS文件有:

$(function() { 
    // do lots and lots of stuff 
}); 

與沒有使用Javascript內部的HTML(PHP)網頁上。這是一個性能災難,這是相對有效的選擇的選擇,意爲永不:

$(".someClass").doStuff(); 

相反:

$("div.someClass").doStuff(); 

等。花費了大約一秒鐘的時間來執行所有的Javascript,儘管其中95%沒有做任何事情。我的建議?如果你想要一個高度敏感的網站不要這樣做

而是把類似這樣的功能在外部JS:

function activate_accordion() { 
    $("#accordion").accordion(); 
} 

這當然是一個簡單的例子。但關鍵是這樣的:沒有Javascript應該會自動執行在你的外部Javascript文件,除非絕大多數頁面使用它。您的外部Javascript文件應該只是在單個頁面上被調用的必要功能的集合。

然後每個頁面的HTML裏面放於:

<script type="text/javascript"> 
$(function() { 
    activate_accordion(); 
} 
</script> 

,所以你只能執行你實際上是使用JavaScript。是的,這樣做的工作稍微多一點,因爲你必須知道每個頁面在做什麼/使用什麼,但是在全球範圍內這樣做可能會很快失去控制。

以這種方式將Javascript執行時間減少到50-100ms(1-2秒)。

+0

讓我看看我是否明白你的意思。您可以在名爲activate_ {functionname}的全局包含函數上定義函數,然後在使用該函數的標記上添加實際的activate_ {functionname}調用。所以最後你和所有的activate_ {functionname}都有一個契約,你可以在標記上添加每個頁面所需要的所有函數。這是準確的嗎? – Geo 2009-10-07 16:08:21

+0

就是這樣。然而,這個主題有很多變化。例如,您可以使用一個名爲use()或import()的函數,併爲其提供一個常量列表,以便在頁面上使用這些函數。 YUI使用這種方法,但它也自動處理依賴關係。 – cletus 2009-10-07 16:24:41

+0

感謝您的信息。我無法理解use()import()的比喻,但總的來說感謝。 – Geo 2009-10-07 16:52:04

2

它會尋找這樣一個元素,並且,由於沒有任何元素,它不會做任何事情。

jQuery的selector library針對性能進行了高度優化,所以我不擔心它。

特別是,一個簡單的#id選擇器變成了一個調用瀏覽器的原生getElementById,它可以被認爲是相當快的。

如果您真的擔心,請在不同的瀏覽器中進行測量。

1

的代碼將被要求每一個頁面加載和執行會去是這樣的:

  • $("#accordion").accordion()
    1. 查找匹配的元素:
      1. "#accordion" ID查找是非常快
    2. 應用功能N到所有匹配的元素:
      • 如果沒有#accordion元素,那麼它會立刻幾乎沒有返回做任何

你只需要擔心在兩種情況下,IMO:

  1. 您有一個非常複雜的選擇器。
  2. 您正在調用元素上的很多功能。

在案例2中,這是更爲常見的,我的工作圍繞它通過這樣做:

$el = $('#myElement'); 
if ($el.length) { 
    $el 
     .find("div") 
     .each(function() { .. }) 
     .parents() 
    // etc... 
} 

我剛剛把一個基準測試其實這多少影響了。您可以see the resultsthe code如果你喜歡:

簡而言之:

// doing this: 
var $f = $('#fakeElement'); 
if ($f.length) $f.find('div'); 

// is almost twice as fast as this: 
$('#fakeElement').find('div'); 

// For 10000 iterations, 404ms vs 788ms in my tests 
+0

沒有特別的理由不把它寫成一條長鏈;如果第一部分不匹配任何東西,鏈將不會繼續。例如:$(「#myElement」)。find(「div」)。each(...)。parents()甚至(在本例中)$(「#myElement div」)。each(...)。父母()。 – 2009-10-07 03:21:29

+0

鏈將繼續......調用每個函數並返回一個空的jQuery結果集。根據你在那裏鏈接了多少個函數,開銷(即使是從一個空集合)可能會顯着增加。 – nickf 2009-10-07 05:02:45

+0

@Sixten:查看我剛剛編輯進這個答案的測試結果......即使在一個空集上只有一個簡單的'.find',它的速度就會慢得多。 – nickf 2009-10-07 05:17:18

2

是的,從技術上jQuery將花費一定的時間與「日期選擇器」的ID在尋找的元素。

但是,由於您選擇的是ID和ID,並且每頁僅做一次,所需時間可能非常短,甚至無法可靠地進行測量。

現在,如果這段代碼被埋在一個循環中,並且會以瘋狂的頻率執行,你可能會擔心這個問題。但事實並非如此。

這是小東西,不要爲此而出汗。我敢肯定,如果你看起來夠辛苦的話,你可以找到十幾個優化結果,而不用擔心這個問題。

0

由於jQuery是無狀態的,它將不得不查看這個。你可以通過在變量中設置元素來限制影響,然後當你需要時,你看看你在javascript代碼中保存了什麼,然後使用它。

像這樣的優化可以幫助解決任何性能問題,但是,正如SLak提到的,這個調用非常快,但是,您可以在不同的瀏覽器上調用它,並查看是否要加速。

0

如果你有一大塊的代碼是依賴於元素的存在,你總是可以有條件地執行:

if($('#accordion').length > 0){ 
    // 20 lines of #accordion-dependent code here 
} 
1

爲什麼不在本地通話混?

以下每一項都運行10,000次迭代。

$('div#datepicker'); 
// 179ms 

$('#datepicker').find('div'); 
// 65ms 

var $dp = $('#datepicker'); if ($dp.length) $dp.find('div'); 
// 32ms 

if (document.getElementById('datepicker')) $('#datepicker').find('div'); 
// 1ms 
+1

jQuery的部分原因是抽象本機實現。 'getElementById'現在得到普遍支持,但幾年前,並非所有瀏覽器都支持。 – Hollister 2011-06-28 23:54:32

+1

另外,你的例子不是等價的:第一個返回一個元素,其餘的可能返回多個元素。 – Hollister 2011-06-29 00:00:20

0

$('body').find("#datapicker") ...是相當快的。

我從一位核心貢獻者那裏得到了一些建議。就是這樣 - >

if($("#datepicker")[0]) {...} 

但速度更快。

相關問題