JavaScript - помочь с сокращением document.getelementbyid DOM вызовов или переписать алгоритм - PullRequest
0 голосов
/ 05 сентября 2011

У меня есть эта функция, которую я написал, которая имеет несколько вызовов document.getelementbyid к повторяющемуся шаблону идентификаторов (a, b, c, d, e, f), который находится внутри цикла for, что делает их a1, b1, c1 ... a6, b6, c6 ... Возможно присвоить переменную для document.getelementbyid без указания конкретных идентификаторов, т.е. var xyz = document.getelementbyid; Я помню, как наткнулся на пост, в котором показаны разные способы написания телефонных звонков.

Или лучшее, что я могу сделать в этом случае, это var dom = document;

По сути, у меня есть несколько строк div, и каждый div имеет уникальный идентификатор.

Спасибо.

Редактировать 2

Я не мог заставить код Эндрю работать, но я последовал его идее и переписал код, он оказался проще, чем я задумал изначально. Последний блок кодов внизу.

function display (namearr, current) {


var tldstr = document.getElementById("dlist").innerHTML;
tldstr = tldstr.slice(0, -1)
var tldarr = tldstr.split(",");

index = current - 1;    
var arrlen = tldarr.length;
var img = "<img src='../loader1.gif' alt='loading' width='40' />";

for (z=0; z<10; z++){


  i=z+1;
  if (index >= arrlen) {
        document.getElementById("a"+i).className = "tldn";
        document.getElementById("b"+i).className = "tldn";
        document.getElementById("c"+i).className = "tldn";
        document.getElementById("d"+i).className = "tldn";
        document.getElementById("e"+i).className = "tldn";
        document.getElementById("f"+i).className = "tldn";
  }

  else if ( tldarr[index] == "n" || tldarr[index].length != 6) 
        {

        document.getElementById("a"+i).innerHTML = img;
        document.getElementById("b"+i).innerHTML = img;
        document.getElementById("c"+i).innerHTML = img;
        document.getElementById("d"+i).innerHTML = img;
        document.getElementById("e"+i).innerHTML = img;
        document.getElementById("f"+i).innerHTML = img;


        }//close  first elseif
  else {
        tldstr = tldarr[index];

        document.getElementById("a"+i).className = "tld"+tldstr.charAt(0);
        document.getElementById("b"+i).className = "tld"+tldstr.charAt(1);
        document.getElementById("c"+i).className = "tld"+tldstr.charAt(2);
        document.getElementById("d"+i).className = "tld"+tldstr.charAt(3);
        document.getElementById("e"+i).className = "tld"+tldstr.charAt(4);
        document.getElementById("f"+i).className = "tld"+tldstr.charAt(5);

       }//close second elseif

    index++;
    }//close first for loop


}//end of  function

HTML-разметка

<div class="xyz">

    <div  class="tldn" id="a1">xxx</div>
    <div  class="tldn" id="b1">xxx</div>
    <div class="tldn" id="c1">xxx</div>
    <div  class="tldn" id="d1">xxx</div>
    <div class="tldn" id="e1">xxx</div>
    <div class="tldn" id="f1">xxx</div>
 </div>

  <div class="123">

    <div  class="tldn" id="a2">xxx</div>
    <div  class="tldn" id="b2">xxx</div>
    <div class="tldn" id="c2">xxx</div>
    <div  class="tldn" id="d2">xxx</div>
    <div class="tldn" id="e2">xxx</div>
    <div class="tldn" id="f2">xxx</div>
  </div>

Рабочий код

function display (namearr, current) {
var aarr = [];
var barr = [];
var carr = [];
var darr = [];
var earr = [];
var farr = [];

for (var z=1; z<=10; z++) {
  c = z-1;
  aarr[c] = document.getElementById("a"+z);
  barr[c] = document.getElementById("b"+z);
  carr[c] = document.getElementById("c"+z);
  darr[c] = document.getElementById("d"+z);
  earr[c] = document.getElementById("e"+z);
  farr[c] = document.getElementById("f"+z);

 var tldstr = document.getElementById("dlist").innerHTML;
    tldstr = tldstr.slice(0, -1)
    var tldarr = tldstr.split(",");

    index = current - 1;    
    var arrlen = tldarr.length;
    var img = "<img src='../loader1.gif' alt='loading' width='40' />";

    for (i=0; i<10; i++){


      if (index >= arrlen) {
            aarr[i].className = "tldn";
            barr[i].className = "tldn";
            carr[i].className = "tldn";
                .
                .
                .

      }

      else if ( tldarr[index] == "n" || tldarr[index].length != 6) 
            {

            aarr[i].innerHTML = img;
            barr[i].innerHTML = img;
            .
                .
                .


            }//close  first elseif
      else {
            tldstr = tldarr[index];

            aarr[i].className = "tld"+tldstr.charAt(0);
            aarr[i].className = "tld"+tldstr.charAt(1);
            .
            .
                .
           }//close second elseif

        index++;
        }//close first for loop

}

Ответы [ 6 ]

1 голос
/ 05 сентября 2011

Мне кажется, это вопрос из двух частей:

Сокращение обхода цепи прицела

Одна из стратегий оптимизации, на которую вы ссылаетесь, - это присвоение локальной (функциональной) переменной. Обычно это делается для того, чтобы минимизировать объем цепочки областей действия, который необходимо пройти при доступе к этой переменной. Книга «Высокопроизводительный Javascript» ( PDF соответствующей главы ) хорошо описывает это.

Вдоль этих строк наложение псевдонима document на переменную уровня функции может привести к некоторому незначительному увеличению эффективности за счет сокращения цепочки областей действия. Однако это, возможно, микрооптимизация, и она не справится с основным потенциальным замедлением, о котором вы упоминаете, а именно с повторяющимися вызовами DOM в цикле.

Упрощение вызовов DOM

Для лучшей управляемости и эффективности кода вы должны исключить запросы к большому количеству элементов по идентификатору так, как вы это делаете (хотя получение элемента по идентификатору очень эффективно, повторные вызовы действительно складываются, и в этом случае возможно, сделать код менее понятным). Хороший способ сделать это - использовать jQuery или другую библиотеку с хорошей поддержкой селекторов. Использование библиотеки (в примере ниже предполагается, что jQuery) сократит объем кода, который вам нужно написать, при обработке различий между браузерами.

Подумайте, что общего у элементов, на которые вы ссылаетесь, и как запросить их как один набор. Хорошая стратегия состоит в том, чтобы назначать имена классов (в коде сервера, где вы в настоящее время устанавливаете идентификаторы элементов) для каждого из элементов, поясняя, к какому набору (-ам) принадлежит каждый. class="cell type_a set_4" установит классы для элемента, который в настоящее время имеет идентификатор "a4".

Затем получите полный набор элементов одновременно. Указание родительского элемента сделает вещи более эффективными:

var elements = $('#id_of_parent_element .cell')

После того, как вы получили элементы, вы можете затем отфильтровать список до нужных без дополнительных вызовов в DOM. Вот окончательный код цикла (обратите внимание, что он также гораздо менее многословен, чем получение всех этих по идентификатору):

var elements = $('#id_of_parent_element .cell'); // get the "cell" elements

for (z=0; z<10; z++){

    var current_elements = elements.filter('.set_' + z); // filter to numbered set

    if (index >= arrlen) {
        current_elements.addClass('tldn');
    } else if ( tldarr[index] == "n" || tldarr[index].length != 6)  {
        current_elements.innerHTML = img;
    } else {
        var tldstr = tldarr[index];
        current_elements.each(function(index, element) {
            $(this).addClass("tld" + tldstr.charAt(index));
        });
    }
}

Обратите внимание, что количество и время выполнения вызовов в DOM будут варьироваться в зависимости от браузера, поскольку jQuery пытается использовать собственные функции, такие как document.getElementsByClassName, где это возможно, при этом поддерживая более старые версии, у которых их не было. Но общий результат должен заключаться в меньшем количестве вызовов DOM, повышении предельной эффективности и уменьшении количества поддерживаемых строк кода.

1 голос
/ 05 сентября 2011

Нет, вы не можете назначить метод переменной. Вы можете обернуть его в функцию.

function setClassName(id, className) {
   document.getElementByID(id).className = className;
}

if (index >= arrlen) {
    setClassName("a"+i, "tldn");
    setClassName("b"+i, "tldn");
    //etc
}

Или, что еще лучше, создайте массив ваших писем, а затем передайте его тоже

//pseudocode
var foo = array(a, b, c, d, e, f);

function ( foo, className ) {
   //iterate over array and apply class name
}
0 голосов
/ 05 сентября 2011

Если счетчик div s постоянен во время существования страницы, то следующий код может уменьшить количество вызовов document.getElementsById и увеличить скорость функции display():

var divsObj={a:[],b:[],c:[],d:[],e:[],f:[]};
for (var i=1; i<=10; i++) {
  divsObj.a.push(document.getElementById("a"+i));
  divsObj.b.push(document.getElementById("b"+i));
  divsObj.c.push(document.getElementById("c"+i));
  divsObj.d.push(document.getElementById("d"+i));
  divsObj.e.push(document.getElementById("e"+i));
  divsObj.f.push(document.getElementById("f"+i));
}

function display (namearr, current) {
  var tldstr = document.getElementById("dlist").innerHTML;
  tldstr = tldstr.slice(0, -1)
  var tldarr = tldstr.split(",");

  //index = current - 1;
  var index = current - 1; // if *index* not global or closur variable use *var*
  var arrlen = tldarr.length;
  var img = "<img src='../loader1.gif' alt='loading' width='40' />";

  for (var i=0; i<10; i++) {
    if (index >= arrlen) {
      divsObj.a[i].className = "tldn";
      divsObj.b[i].className = "tldn";
      divsObj.c[i].className = "tldn";
      divsObj.d[i].className = "tldn";
      divsObj.e[i].className = "tldn";
      divsObj.f[i].className = "tldn";
    }
    else if ( tldarr[index] === "n" || tldarr[index].length !== 6) {
      divsObj.a[i].innerHTML = img;
      divsObj.b[i].innerHTML = img;
      divsObj.c[i].innerHTML = img;
      divsObj.d[i].innerHTML = img;
      divsObj.e[i].innerHTML = img;
      divsObj.f[i].innerHTML = img;
    }
    else {
      tldstr = tldarr[index];
      divsObj.a[i].className = "tld"+tldstr.charAt(0);
      divsObj.b[i].className = "tld"+tldstr.charAt(1);
      divsObj.c[i].className = "tld"+tldstr.charAt(2);
      divsObj.d[i].className = "tld"+tldstr.charAt(3);
      divsObj.e[i].className = "tld"+tldstr.charAt(4);
      divsObj.f[i].className = "tld"+tldstr.charAt(5);
    }
    index++;
  }
}
0 голосов
/ 05 сентября 2011

Хотите сделать ярлык для document.getElementById?Если это так, вы можете сделать это

yourshortcut = function(id) { return document.getElementById(id); };
0 голосов
/ 05 сентября 2011

Если вы используете шаблон модуля и передаете его окну и документу в качестве параметров, тогда любой хороший минификатор уменьшит размер документа до одной буквы.Также рассмотрите возможность принятия undefined в качестве третьего параметра, который вы не передаете при вызове своей функции.

Я настоятельно рекомендую прочитать http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

Мне нравится использовать формат Loose Augmentation, с дополнительнымпараметры:

var MODULE = (function (my, window, document, undefined) { 
    // add capabilities... 

    return my; 
}(MODULE || {}, window, document));

Обратите внимание, как это гарантирует, что undefined не определен - то, что может быть установлено вредоносным кодом.Этот топ-топ от 10 вещей Пола Айриша, которые я узнал из источника jQuery , также отлично читается.

0 голосов
/ 05 сентября 2011

Я не рекомендую это, но я думаю, что вы хотите назначить функцию как переменную (т.е. указатель функции).

var getById = document.getElementById;

Тогда это просто:

getById("a"+i).className = "tldn";

Я бы предложил вместо этого использовать библиотеку, такую ​​как prototype или jQuery , чтобы очистить ваш код.Тогда ваш код можно написать гораздо более кратко:

$ ("# a" + i) .addClass ("tldn");

Кроме того, просто какзаметка о стиле - почему вы все равно назначаете индивидуальные идентификаторы?Звучит так, как будто вы должны поместить класс «tldn» в разметку, чтобы ссылаться на группу элементов (в конце концов, это целевое использование атрибута «класс» для элемента).Затем вы можете использовать document.getElementsByClassName("tldn") для ссылки на все ваши элементы, а не писать шесть строк кода для ссылки на группу элементов.

Примечание: getElementsByClassName не работает в старых браузерах, таких как IE8 и ниже .

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