2011-01-14 2 views
3

В Internet Explorer 7, этот код выполняется последовательно в мс:Почему скорость выполнения этого кода отличается?

function updateObjectValues() {  
    $('.objects').html(12345678); // ~500 DIVs 
} 

однако, этот код выполняется последовательно в мс:

function updateObjectValues() { 
    $('.objects').html('12345678'); // ~500 DIVs 
} 

Передача число превышает 3 раза быстрее, чем строка. Почему эти результаты так резко отличаются? И есть ли способ помочь исполнению строки?

+5

вероятно потому, что строки должны быть разобраны на содержание HTML, а номера нет. Попробуйте запустить тот же тест с .text вместо .html и посмотреть, есть ли еще большая разница. –

+0

Я верю, потому что jquery анализирует строку как html. – Ish

+4

Вы пытались использовать 'text' вместо' html'? Было бы интересно. –

ответ

9

Если вы посмотрите на исходный код jQuery (или даже незавершенная производственная версия), вы увидите, что ветвь if (typeof value === "string" ... кода значительно более сложна, чем окончательная версия else, которая будет иметь место при прохождении номера.

Вот 1.4.4 код, если значение является строкой:

} else if (typeof value === "string" && !rnocache.test(value) && 
    (jQuery.support.leadingWhitespace || !rleadingWhitespace.test(value)) && 
    !wrapMap[ (rtagName.exec(value) || ["", ""])[1].toLowerCase() ]) { 

    value = value.replace(rxhtmlTag, "<$1></$2>"); 

    try { 
     for (var i = 0, l = this.length; i < l; i++) { 
      // Remove element nodes and prevent memory leaks 
      if (this[i].nodeType === 1) { 
       jQuery.cleanData(this[i].getElementsByTagName("*")); 
       this[i].innerHTML = value; 
      } 
     } 

    // If using innerHTML throws an exception, use the fallback method 
    } catch(e) { 
     this.empty().append(value); 
    } 
} 

Вот что он делает с номером:

} else { 
    this.empty().append(value); 
} 

Очевидно, накладные расходы всех этих дополнительных проверок и вызовы функций. Я имею в виду, что даже в заявлении if наверху есть три теста регулярных выражений, поиск по карте и строчка, сделанная в нижнем регистре   —, и это до того, как мы войдем в тело утверждения (если мы это сделаем , возможно, одна из проверок возвращает false), которая включает в себя дополнительное регулярное выражение (как часть параметризованной замены) и петлю ...

+3

+1 для глубокого рытья и сделать это научным путем;) –

2

Номера могут храниться двоично, возможно, в одном регистре. Строки должны храниться как, ну, строка, в памяти. Поэтому оптимизирующий интерпретатор или JIT-компилятор будет использовать возможную скорость, которую предоставляет целое число.

Кроме того, как указывает Мартин Йесперсен, функция html() может обрабатывать строки по-разному, чем числа, выполняя больше работы над ней - если она осознает различия. Престижность Мартину там.

+0

* «Таким образом, оптимизирующий интерпретатор или JIT-компилятор воспользуется ...» * Итак, это позволяет IE7, затем , с его классным мусором JavaScript-переводчиком. ;-) –

+0

Действительно :). Но в последнее время производители браузеров конкурировали за то, у кого самый быстрый JS-движок, поэтому сейчас новые браузеры будут реализовывать такие или подобные методы увеличения скорости. – foo

3

Я просто побежал испытание, и, казалось, подтверждало мое первоначальное понятие:

.text(string) столь же быстро, как .html(number) эрго должна быть строка синтаксического анализа накладных расходов в .html(string)

ли это накладные расходы в IE7 или в JQuery мне непонятно. Ie8, похоже, не имеет такой же проблемы, что предполагает, что проблема не в i jQuery, но тогда ie8 имеет гораздо более быстрый js-движок, чем ie7 ...

1

As TJ Кроудер указывает на то, что код the source показывает, что путь кода совсем другой для строки; как ни странно, ассоциированная комментарий предполагает, что это в попытке использовать «ярлык»:

html: function(value) { 
     if (value === undefined) { 
      return this[0] && this[0].nodeType === 1 ? 
       this[0].innerHTML.replace(rinlinejQuery, "") : 
       null; 

     // See if we can take a shortcut and just use innerHTML 
     } else if (typeof value === "string" && !rnocache.test(value) && 
      (jQuery.support.leadingWhitespace || !rleadingWhitespace.test(value)) && 
      !wrapMap[ (rtagName.exec(value) || ["", ""])[1].toLowerCase() ]) { 

      value = value.replace(rxhtmlTag, "<$1></$2>"); 

      try { 
       for (var i = 0, l = this.length; i < l; i++) { 
        // Remove element nodes and prevent memory leaks 
        if (this[i].nodeType === 1) { 
         jQuery.cleanData(this[i].getElementsByTagName("*")); 
         this[i].innerHTML = value; 
        } 
       } 

      // If using innerHTML throws an exception, use the fallback method 
      } catch(e) { 
       this.empty().append(value); 
      } 

     } else if (jQuery.isFunction(value)) { 
      this.each(function(i){ 
       var self = jQuery(this); 

       self.html(value.call(this, i, self.html())); 
      }); 

     } else { 
      this.empty().append(value); 
     } 

     return this; 
    }, 
Смежные вопросы