JavaScript: функция оптимизации для создания вертикальной шкалы времени - PullRequest
0 голосов
/ 13 октября 2011

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

Есть ли способы улучшить / оптимизировать то, что я создал до сих пор?

В идеале мне нужны способы минимизации дублирования, посторонних вызовов и т. Д.

Вот мой рабочий код: http://jsfiddle.net/bL25b/

function timeline( start, abbr, hours )
{
  var a = 0,
      start,
      abbr,
      hours,
      time = document.getElementById('timeline');

  hours = (!hours) ? 12 : hours;

  for(a = a + start; a <= hours + start; a++)
  {
    if(a > 12)
    {
      time.innerHTML += '<li>' + (a - 12) + ':00 ' +
                          ( abbr == 'AM' ? 'PM' : 'AM' ) +
                        '</li>';

      time.innerHTML += '<li>' + (a - 12) + ':30 ' +
                          ( abbr == 'PM' ? 'AM' : 'PM' ) +
                        '</li>';
    }
    else
    {
      time.innerHTML += '<li>' + a + ':00 ' +
                          ( abbr == 'AM' ? (a == 12) ? 'PM' : 'AM' : 'PM' ) +
                        '</li>';

      time.innerHTML += '<li>' + a + ':30 ' +
                          ( abbr == 'AM' ? (a == 12) ? 'PM' : 'AM' : 'PM' ) +
                        '</li>';
    }
  }
}

timeline( 9, 'AM', 12 );

Допустимые аргументы функции:

  • начало: время начала (0-12)
  • аббревиатура: Am / PM аббревиатура
  • часы: количество часов для отображения

Ответы [ 5 ]

3 голосов
/ 13 октября 2011

См. обновленный код :

function timeline( start, abbr, hours )
{
    var a = 0,
        abbr = abbr || 'AM',
        hours = hours || 12,
        time = document.getElementById('timeline'),
        timelineHTML = [];

    for (a = a + start; a <= hours + start; a++)
    {
        if (a % 12 === 0) {
            abbr = abbr === 'PM' ? 'AM' : 'PM';
        }

        timelineHTML.push('<li>' + (a % 12 === 0 ? 12 : a % 12) + ':00 ' + abbr + '</li>');
        timelineHTML.push('<li>' + (a % 12 === 0 ? 12 : a % 12) + ':30 ' + abbr + '</li>');
    }

    time.innerHTML = timelineHTML.join('');
}

timeline( 9, 'AM', 24 );

Самым значительным изменением является минимизация операций DOM - мы сохраняем наши будущие элементы в массиве и добавляем их сразу.

Во-вторых, я удалил ненужный и запутанный блок if..else. Переключение между «AM» и «PM» происходит каждые 12 часов, поэтому подойдет простой модульный оператор.

Часть, где (a % 12 === 0 ? 12 : a % 12) может все еще сбивать с толку, но она по-прежнему отображает 12: 30 AM вместо 0: 30 AM . Вы можете изменить его на короткий (a % 12), если хотите.

Наконец, вы использовали hours = (!hours) ? 12 : hours, тогда как простой hours = hours || 12 более читабелен.

3 голосов
/ 13 октября 2011

Не используйте innerHTML += каждый раз, используйте массив для хранения html-частичек, затем используйте метод join, чтобы соединить их со строкой и назначить строку для innerHTML

2 голосов
/ 13 октября 2011

Если вы собираетесь прикоснуться к innerHTML элемента, обычно считается оптимальным сделать это сразу. Кроме того, существующий цикл for должен обрабатывать сложение каждый раз, и лучше всего заранее определить конечную точку цикла.

var newHTML = '';
var finish = hours+start;

for(a=a+start; a <= finish; a++)
{
    if(a > 12)
    {
        newHTML += '<li>' + (a-12) + ':00 ' + ( abbr == 'AM' ? 'PM' : 'AM' ) + '</li>';
        newHTML += '<li>' + (a-12) + ':30 ' + ( abbr == 'PM' ? 'AM' : 'PM' ) + '</li>';
    }
    else
    {
       newHTML += '<li>' + a + ':00 ' + ( abbr == 'AM' ? (a==12) ? 'PM' : 'AM' : 'PM' ) + '</li>';
       newHTML += '<li>' + a + ':30 ' + ( abbr == 'AM' ? (a==12) ? 'PM' : 'AM' : 'PM' ) + '</li>';
   }
}

time.innerHTML += newHTML;
2 голосов
/ 13 октября 2011

Вместо innerHTML используйте:

  1. createElement - для создания нового элемента LI

  2. insertAfter - чтобы вставить его вконец

Добавить новый узел к существующему.Это было бы быстрее, чем добавление innerHTML к существующему innerHTML.

1 голос
/ 13 октября 2011

Все остальные покрывали широкие мазки (особенно @Lapple), так что вот пара очень незначительных низко висящих предметов:

hours = (!hours) ? 12 : hours;

Можно сократить до:

hours = hours || 12;

... и является более читабельной идиомой (я думаю) для большинства программистов JavaScript.

Редактировать re: Ваш комментарий:

Я не знаю названия для этой конкретной идиомы. Как и в большинстве языков программирования, JavaScript использует оценку короткого замыкания для логических выражений, т. Е. Учитывая X || Y, если интерпретатор уже может сказать, что значение выражения будет из X (потому что X является "правдивым" ), это никогда не мешает оценить Y. Таким образом, вы можете сделать что-то вроде true || delete_everything(), уверенное, что delete_everything никогда не вызовут. Аналогично в X && Y, если X является «ложным», то Y никогда не будет оцениваться.

Это может быть старая шляпа для вас. То, что делает JavaScript, менее распространено, однако, это то, что вы могли бы назвать оценкой «последнего значения» (это термин, используемый страницей Википедии, но я не уверен, является ли это общим термином вообще). Вместо возврата true или false из логического выражения, как в Java, или 1 или 0, как в C, в JavaScript он просто возвращает последнее значение , оцененное.

Возьмите выражение hours || 12. Если hours равно undefined (ложное значение в JavaScript), то интерпретатор просто вернет второй операнд (поскольку в OR «истинность» выражения всегда равна правдивости второго операнда, когда первый операнд ложный). Однако, если hours является правдивым - скажем, 9 или "banana", то выражение после его вычисления замкнется и вернет это значение. Повторюсь, но в коде:

var hours; // declared but has the value undefined

console.log( hours || 12 ); // `hours` (undefined) is falsy
// => 12                    // so return the second operand

hours = 9;
console.log( hours || 12 ); // `hours` is truthy--short-circuit & return `hours`
// => 9

hours = "banana";
console.log( hours || 12 ); // `"banana"` is also truthy
// => "banana";

console.log( 12 || hours ); // `12` is truth--short-circuit & return `12`
// => 12

Кстати, в таких языках, как Ruby, у которых есть оператор ||=, есть еще более короткая форма этой идиомы, довольно распространенная:

hours = nil          # `nil` is like `null`

hours = hours || 12  # just like in JavaScript
# => 12

# but the below is equivalent:

hours = nil

hours ||= 12
# => 12

Так что в Ruby нередко можно увидеть такие методы:

def foo(bar, baz = nil) # `baz` defaults to `nil` when no 2nd argument is given
  baz ||= get_default_baz()

  puts bar + baz        # `puts` is like `print` or `echo` in other languages
end

def get_default_baz     # a trivial example
  "WXYZ"
end

foo('ABC', 'DEF')
# => ABCDEF

foo('ABC')
# => ABCWXYZ

(конец редактирования)

А здесь:

var a = 0,
    start,
    abbr,
    hours,
    time = document.getElementById('timeline');

hours = (!hours) ? 12 : hours;

... вы объявляете hours в строке 4, а затем назначаете его в строке 7, когда вы можете сделать оба одновременно:

var a = 0,
    // ...
    hours = hours || 12
    // ...
;
...