Почему этот кусок кода Javascript такой медленный? - PullRequest
2 голосов
/ 07 мая 2009

У меня есть этот фрагмент кода Javascript, который занимает около 600 мс при каждом вызове в Internet Explorer. Время, затрачиваемое в других браузерах, ничтожно.

var _nvs_currentTab;
var _nvs_zoomfield;
var _nvs_centerfield;
var _nvs_globsearch;
var _nvs_category;
var _nvs_favsonly;
var _nvs_wishonly;
var _nvs_friendfavsonly;
var _nvs_newitemsonly;
var _nvs_globsearchOld;
var _nvs_catOld;
var _nvs_favsonlyOld;
var _nvs_wishonlyOld;
var _nvs_friendFavsonlyOld;
var _nvs_newItemsOnlyOld;

function saveState()
{
    if (!_nvs_currentTab)
    {
        var f = document.getElementById;
        _nvs_currentTab = f('currentTab');
        _nvs_zoomfield = f('zoomfield');
        _nvs_centerfield = f('centerfield');
        _nvs_globsearch = f("globsearch");
        _nvs_category = f("category");
        _nvs_favsonly = f("favsonly");
        _nvs_wishonly = f("wishonly");
        _nvs_friendfavsonly = f("friendfavsonly");
        _nvs_newitemsonly = f("newitemsonly");
        _nvs_globsearchOld = f("globsearchOld");
        _nvs_catOld = f("categoryOld");
        _nvs_favsonlyOld = f("favsonlyOld");
        _nvs_wishonlyOld = f("wishonlyOld");
        _nvs_friendFavsonlyOld = f("friendFavsonlyOld");
        _nvs_newItemsOnlyOld = f("newItemsOnlyOld");
    }

    // get all state vars
    var navState= new Object();
    navState.page = currentPage;
    navState.currentTab = _nvs_currentTab.value;
    navState.zoomfield = _nvs_zoomfield.value;
    navState.centerfield = _nvs_centerfield.value;
    navState.globsearch = _nvs_globsearch.value;
    navState.category = _nvs_category.value;
    navState.favsonly = _nvs_favsonly.checked;
    navState.wishonly = _nvs_wishonly.checked;
    navState.friendfavsonly = _nvs_friendfavsonly.checked;
    navState.newitemsonly = _nvs_newitemsonly.checked;
    navState.globsearchOld = _nvs_globsearchOld.value;
    navState.catOld = _nvs_catOld.value;
    navState.favsonlyOld = _nvs_favsonlyOld.value;
    navState.wishonlyOld = _nvs_wishonlyOld.value;
    navState.friendFavsonlyOld = _nvs_friendFavsonlyOld.value;
    navState.newItemsOnlyOld = _nvs_newItemsOnlyOld.value;
    // build new url with state
    var url = new StringBuffer();
    url.append("#");
    for (var i in navState)
    {
        if (i != "page")
            url.append("&");
        url.append(i).append("=").append(navState[i]);
    }
    // set it
    window.location.href = url.toString();
}

Вот как выглядит дерево вызовов из профилировщика IE8:

saveState               1    615,00 ms
  f                    15      1,00 ms
  String.split          1      0,00 ms
    Array               1      0,00 ms
  Object                1      0,00 ms
  StringBuffer          1      0,00 ms
  append               64      0,00 ms
    Array.push         64      0,00 ms
  toString              1      0,00 ms
    Array.join          1      0,00 ms
  Object.valueOf       63      0,00 ms
  Function.toString    63      0,00 ms

Я использую реализацию StringBuffer:

function StringBuffer() { 
    this.buffer = []; 
} 

StringBuffer.prototype.append = function append(string) { 
    this.buffer.push(string); 
    return this; 
}; 

StringBuffer.prototype.toString = function toString() { 
    return this.buffer.join(""); 
}; 

Редактировать: Обновленный код, для выполнения в среднем требуется 397 мс.

var _nvs_currentTab;
var _nvs_zoomfield;
var _nvs_centerfield;
var _nvs_globsearch;
var _nvs_category;
var _nvs_favsonly;
var _nvs_wishonly;
var _nvs_friendfavsonly;
var _nvs_newitemsonly;
var _nvs_globsearchOld;
var _nvs_catOld;
var _nvs_favsonlyOld;
var _nvs_wishonlyOld;
var _nvs_friendFavsonlyOld;
var _nvs_newItemsOnlyOld;

function saveState()
{
    if (!_nvs_currentTab)
    {
        var _f = document.guideForm;
        _nvs_currentTab = _f.currentTab;
        _nvs_zoomfield = _f.zoomfield;
        _nvs_centerfield = _f.centerfield;
        _nvs_globsearch = _f.globsearch;
        _nvs_category = _f.category;
        _nvs_favsonly = _f.favsonly;
        _nvs_wishonly = _f.wishonly;
        _nvs_friendfavsonly = _f.friendfavsonly;
        _nvs_newitemsonly = _f.newitemsonly;
        _nvs_globsearchOld = _f.globsearchOld;
        _nvs_catOld = _f.categoryOld;
        _nvs_favsonlyOld = _f.favsonlyOld;
        _nvs_wishonlyOld = _f.wishonlyOld;
        _nvs_friendFavsonlyOld = _f.friendFavsonlyOld;
        _nvs_newItemsOnlyOld = _f.newItemsOnlyOld;
    }

    // build new url with state
    var url = new StringBuffer();
    url.append("#");
    url.append('currentPage=').append(currentPage);
    url.append('&currentTab=').append(_nvs_currentTab.value);
    url.append('&zoomfield=').append(_nvs_zoomfield.value);
    url.append('&centerfield=').append(_nvs_centerfield.value);
    url.append('&globsearch=').append(_nvs_globsearch.value);
    url.append('&category=').append(_nvs_category.value);
    url.append('&favsonly=').append(_nvs_favsonly.checked);
    url.append('&wishonly=').append(_nvs_wishonly.checked);
    url.append('&friendfavsonly=').append(_nvs_friendfavsonly.checked);
    url.append('&newitemsonly=').append(_nvs_newitemsonly.checked);
    url.append('&globsearchOld=').append(_nvs_globsearchOld.value);
    url.append('&catOld=').append(_nvs_catOld.value);
    url.append('&favsonlyOld=').append(_nvs_favsonlyOld.value);
    url.append('&wishonlyOld=').append(_nvs_wishonlyOld.value);
    url.append('&friendFavsonlyOld=').append(_nvs_friendFavsonlyOld.value);
    url.append('&newItemsOnlyOld=').append(_nvs_newItemsOnlyOld.value);
    // set it
    window.location.href = url.toString();
}

Ответы [ 3 ]

10 голосов
/ 07 мая 2009

Хорошо, ты не поверишь в это. Я просто попытался удалить следующую строку:

window.location.href = url.toString();

И это уменьшило среднее время выполнения до двух третей миллисекунды. Я знаю, что из профилирования вызов toString очень быстрый, поэтому, очевидно, установка window.location.href выполняется очень медленно (пара сотен мс !!!). Бах, я ненавижу IE.

Примечание. Это чистая установка Internet Explorer, и у меня нет сумасшедших панелей инструментов, замедляющих работу браузера.

2 голосов
/ 07 мая 2009

Кажется, что вы храните поля из какой-либо формы.

Вместо использования document.getElementById() для получения каждого элемента формы попробуйте получить значение элементов формы напрямую:

navState.currentTab = document.formName.currentTab.value;

, где formName - это значение атрибута name тега form, а currentTab - это значение атрибута name элемента формы (т.е. ввод, флажок).

EDIT:

Когда я использовал IE5 и IE5.5 в 2000 году, даже изменилось (сохранить ссылку на элемент формы в переменной) с:

for (i = 0; i < document.form.elements.length; i++) {
  values[i] = document.form.elements[i].value;
}

до:

var form = document.form;
for (i = 0; i < form.elements.length; i++) {
  values[i] = form.elements[i].value;
}

сделал большую разницу.

Боюсь, ничего не изменилось за последние 10 лет: (.

1 голос
/ 07 мая 2009

Вы пытались закомментировать раздел "получить все переменные" и строку window.location.href? Это может быть одна из input s или навигация (например, панель инструментов браузера с ошибками), которая вызывает задержку.

Кстати, на моей тестовой странице все работает нормально, но, возможно, у вас гораздо больше DOM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...