我有以下循环,循环遍历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;
}
第二种选择真的是第一种选择吗?如果是这样,为什么?
答案 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
。