在循环顶部打破循环的明确条件

时间:2013-12-12 11:40:09

标签: javascript

我有以下循环,循环遍历required_types数组并找到链接对象:

for (var i = 0; i < required_types.length; i++)
{
    var linked_objects =linker.linked(required_types[i].type);
}

现在,我想在找到链接了超过0个对象的类型后打破循环,所以我习惯性地这样做:

var has_linked_objects = false;
for (var i = 0; i < required_types.length; i++)
{
    var linked_objects = ctx.linker.linked(required_types[i].type);
    var has_linked_objects = linked_objects > 0;
    if (has_linked_objects)
    {
        break;
    }
}

但是,我最近阅读了 Code Complete 中有趣的章节,其中指出循环中存在的内容应尽可能清晰并在循环开始时说明。这允许读者在检查循环之前知道所有可能的退出条件。所以现在我会以这种方式编写循环:

var has_linked_objects = false;
for (var i = 0; i < required_types.length && has_linked_objects === false; i++)
{
    var linked_objects = ctx.linker.linked(required_types[i].type);
    var has_linked_objects = linked_objects > 0;
}

第二种选择真的是第一种选择吗?如果是这样,为什么?

3 个答案:

答案 0 :(得分:2)

恕我直言,这是不好的建议。这种情况可能会很长,而且不再符合我的心理“为每个”模式。

我读了这个

for (var i = 0; i < required_types.length; i++) {
    if (has_linked_objects) {
        break;
    }
}

作为

for each element in required_types { // easy
    if(found) {
        break;
    }
}

我读了这个

for (var i = 0; i < required_types.length && has_linked_objects === false; i++) {
}

作为

  哇,这是一个复杂的循环!让我仔细阅读一下......   has_linked_objects什么时候改变?   它可以更改为true并在循环的单次迭代中更改为false吗?

我认为考虑简单条件要容易得多:“如果发生这种情况,那就打破”,而不是跟踪循环体中的许多变量,并在下一次迭代中一次测试所有变量。第二种方法可能会使编写函数的其余部分变得更加困难,因为您无法确定哪个条件触发了循环的结束(是否找到了元素?)

答案 1 :(得分:1)

您可以使用some这样的方法

if (required_types.some(function(cType){return ctx.linker.linked(cType) > 0;})) {
   ...
}

这会在第一次迭代时重复迭代数组,返回true。如果我必须在您提供的两个选项之间进行选择,我会选择第二个(使用以下固定代码)

var has_linked_objects = false;
for (var i = 0; i < required_types.length && has_linked_objects === false; i++)
{
    has_linked_objects = ctx.linker.linked(required_types[i].type) > 0;
}

答案 2 :(得分:1)

这是正确的,你应该把所有条件放在循环的头部如果可能的话。如果不可能或者它会使代码更不易读,你当然可以使用休息时间。在你的情况下,循环是如此小和简单,它可能不会产生巨大的差异。如果你真的想确保开发人员知道发生了什么,你仍然可以写一个评论,列出循环中的替代退出点。

// Iterates required_types and breaks on an entry with linked objects
for (var i = 0; i < required_types.length; i++)
{
    ...
    if (has_linked_objects)
    {
        break;
    }
}

如果你需要进一步使用数组中最后使用的元素,在循环开头有第二个条件会引入另一个问题。当循环结束时,i将始终比结果高1。循环后,您必须将i减少一个。并非这样做很复杂,但作为阅读代码的人,我会被困一两秒。

for (var i = 0; i < required_types.length && has_linked_objects === false; i++)
{
    ...
}
i--; // This can easily get overread or misinterpreted

var obj_with_linked_objects = required_types[i];

TL / DR:在这种情况下,我个人更喜欢break