JavaScript:优化创建垂直时间线的功能

发布于 2024-12-09 20:26:00 字数 1326 浏览 2 评论 0原文

我创建了一个简单的函数来迭代 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 );

接受的函数参数:

  • start:开始时间(0-12)
  • abbr:Am/PM 缩写
  • hours:要显示的小时数

I created a simple function to iterate through a for loop and display a vertical timeline.
Can I get some opinions on what I've created so far?

Are there ways to improve/optimize what I've created so far?

Ideally, what I'm after are ways to minimize duplications, extraneous calls, etc.

Here's my working code: 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 );

The function arguments that are accepted:

  • start: start time (0-12)
  • abbr: Am/PM abbreviation
  • hours: number of hours to display

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

孤独难免 2024-12-16 20:26:00

请参阅更新的代码

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 上午。如果需要,您可以将其更改为短的 (a % 12)

最后,您使用了hours = (!hours) 吗? 12:小时,而简单的小时=小时|| 12 更具可读性。

See the updated code:

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 );

The most significant change is minifying the DOM operations — we store our future elements in an array and append them at once.

Secondly, I removed unnecessary and confusing if..else block. The change between 'AM' and 'PM' occures every 12 hours, so a simple modulus operatior will do.

The part where (a % 12 === 0 ? 12 : a % 12) might be still confusing, but it is kept to display 12:30 AM instead of 0:30 AM. You can change it to short (a % 12) if you want.

Finally, you used hours = (!hours) ? 12 : hours, while simple hours = hours || 12 is more readable.

脱离于你 2024-12-16 20:26:00

不要每次都使用 innerHTML +=,使用数组存储 html 部分,然后使用 join 方法将它们连接到字符串并将字符串分配给 内部HTML

Don't use innerHTML += every time, use an array to store the html partials, then use join method to join them to a string and assign the string to innerHTML

伏妖词 2024-12-16 20:26:00

使用:

  1. createElement - 创建新的 LI 元素

  2. insertAfter - 将其插入到末尾

将新节点添加到现有节点。
这比将innerHTML 添加到现有innerHTML 更快。

Instead of innerHTML , use:

  1. createElement - to create new LI element

  2. insertAfter - to insert it in the end

To add new node to existing one.
That would be faster than adding innerHTML to existing innerHTML.

贵在坚持 2024-12-16 20:26:00

如果您要接触某个元素的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;

If you're going to touch an element's innerHTML, it's usually considered optimal to do so all at once. In addition, your existing for loop has to process the addition every time, and it's best to define the finish point of the loop beforehand.

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;
∝单色的世界 2024-12-16 20:26:00

其他人都涵盖了大致的内容(尤其是@Lapple),所以这里有一些非常小的悬而未决的项目:

hours = (!hours) ? 12 : hours;

可以缩短为:

hours = hours || 12;

...并且对于大多数JavaScript程序员来说是一个更易读的习惯用法(我认为)。

编辑回复:您的评论:

我不知道这个特定习语的名称。与大多数编程语言一样,JavaScript 对布尔表达式使用 短路求值,即给定 X|| Y 如果解释器已经知道表达式的值将来自 X (因为 X 是“truthy”),则它永远不会费心去评估 是的。所以你可以做类似 true || 的事情delete_everything() 确信 delete_everything 永远不会被调用。同样在 X && 中Y 如果 X 为“假”,则 Y 将永远不会被计算。

这对你来说可能已经是老生常谈了。 JavaScript 所做的事情不太常见,不过,你可以称之为“最后一个值”评估(这是维基百科页面使用的术语,但我不确定它是否是一个常见术语)。不是像 Java 中那样从布尔表达式返回 truefalse,或者像 C 中那样从布尔表达式返回 10,在 JavaScript 中,它只返回计算的最后一个值

采用表达式 hours || 12..如果 hoursundefined(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;

...您在第 4 行声明 hours ,然后在第 7 行分配它,此时您可以同时执行这两个操作:

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

Everyone else covered the broad strokes (@Lapple especially), so here's a couple very minor low-hanging items:

hours = (!hours) ? 12 : hours;

Can be shortened to:

hours = hours || 12;

...and is a more readable idiom (I think) to most JavaScript programmers.

Edit re: your comment:

I don't know of a name for this particular idiom. Like most programming languages JavaScript uses short-circuit evaluation on boolean expressions, i.e. given X || Y if the interpreter can already tell the value of expression will be from X (because X is "truthy"), it never bothers to evaluate Y. So you could do something like true || delete_everything() confident that delete_everything would never be called. Likewise in X && Y if X is "falsy" then Y will never be evaluated.

This might all be old hat to you. What JavaScript does that's less common, though, is what you could call "last value" evaluation (this is the term the Wikipedia page uses but I'm not sure if it's a common term at all). Instead of returning true or false from a boolean expression as in Java, or 1 or 0 as in C, in JavaScript it just returns the last value evaluated.

Take the expression hours || 12. If hours is undefined (a falsy value in JavaScript), then the interpreter will just return the second operand (since in an OR the "truthiness" of the expression is always equal to the truthiness of the second operand when the first operand is falsy). However, if hours is truthy--say, 9 or "banana", then the expression will short-circuit after evaluating it and return that value. To repeat myself, but in code:

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

Incidentally, in languages like Ruby that have the ||= operator, there's an even shorter form of this idiom that's fairly common:

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

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

# but the below is equivalent:

hours = nil

hours ||= 12
# => 12

So in Ruby it's not uncommon to see methods like this:

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

(End edit)

And here:

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

hours = (!hours) ? 12 : hours;

...you're declaring hours on line 4 and then assigning it on line 7, when you could do both at the same time:

var a = 0,
    // ...
    hours = hours || 12
    // ...
;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文