JavaScript:在循环中添加值到数组,该值也将包含在循环中。

30

如果这是重复的,请原谅,我找不到它。

var a = [1,2,3,4];
a.forEach(function(value){
  if(value == 1) a.push(5);
  console.log(value);
});
我想知道是否有一种方式(任何类型的循环或数据类型),使得在循环期间输出1 2 3 4 5(或以任何顺序,只要这5个数字都出现在其中)。
我想知道是否有一种方式(任何类型的循环或数据类型),使得在循环期间输出1 2 3 4 5(或以任何顺序,只要这5个数字都出现在其中)。
9个回答

61

使用Array.prototype.forEach()不会将回调应用于在执行期间添加或删除的元素。根据规范

forEach处理的元素的范围是在第一次调用callbackfn之前设置的。在调用forEach后附加到数组中的元素将不会被callbackfn访问。

但是,您可以使用标准的for循环,在每次迭代中检查数组的当前长度:

for (var i = 0; i < a.length; i++) {
    if (a[i] == 1) a.push(5);
    console.log(a[i]);
}

@dystroy,我必须说,这段代码可能和你的一样,但是这个回答呈现得更好;-) - Alnitak
真正的、清晰的解释,这确实可能是最好的方法。谢谢。 - Flion

9

显而易见的解决方案:

var a = [1,2,3,4];
for (var i=0; i<a.length; i++){
  var value = a[i];
  if(value == 1) a.push(5);
  console.log(value);
}

3

既然您似乎正在使用Harmony,那么可以考虑使用这样的生成器:

function *iter(array) {
    for (var n = 0; n < array.length; n++)
        yield array[n];
}

然后

var a = [1,2,3,4];

for(var p of iter(a)) {
    if(p == 1) a.push(5)
    console.log(p)
}

打印1 2 3 4 5


不要和谐。抱歉,我忘了提到。我正在使用几乎与ES6 JS相似的TypeScript,任何JavaScript解决方案都适用于我。将代码示例更改为更常规的JS。 - Flion

1
如果您需要使用回调函数而不是for循环的方法,reduce方法将起作用。
var a = [1,2,3,4];
var result = a.reduce(function(total, item) { 
    total.push(item);
    if (item === 4) total.push(5);   
    return total;
}, []);
console.log(result);

0

这是一个快速测试,看起来运行良好:

var a = [1,2,3,4,5];
a.forEach (function (val,index,array) { 
 if (val == 5) {  
  array.push (6);
 };  
 console.log (val); 
});

1
不起作用!...只需将其复制/粘贴到浏览器控制台中并进行测试(我使用的是Chrome版本63.0) - elingerojo

0

楼主在这里。我已经了解到ES6 Sets确实包括在forEach期间添加的项目。

所以,如果你可以使用一个集合而不是一个数组,你可以这样做:

var a = new Set([1,2,3,4]);
a.forEach(function(value){
  if(value == 1) a.add(5);
  console.log(value);
});

确实记录了5。

这只是for循环的另一种选择。当然,集合与数组在几个方面不同,因此您需要了解差异以及它如何影响其他代码。


0
var a = [1,2,3,4];
Object.keys(a).forEach(idx => {
    if(a[idx]==1) a.push(5);
    console.log(a[idx]);
});

2
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

0

更好的替代方案:

if (a.indexOf(1) >= 0) a.push(5);
a.forEach( ... );

好的,也许不是严格意义上更好,因为它会遍历数组两次。但是你应该考虑一下在迭代过程中为什么要修改数组。这是一个不寻常的情况。


请注意,对于数组的 indexOf 在旧版浏览器中需要一个 shim 才能正常工作。此页面上有一个:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf - Matt Browne
@MattBrowne OP正在使用forEach和ES6箭头函数-他不需要使用indexOf的shim。 - Alnitak
是的,这可能有点不寻常,但我特意想在同一个循环内完成它,因为它可以允许在我正在编写的简单推理引擎中采用不同的策略,从而可能导致更好的性能。 - Flion

0
a.forEach(function fn(item, index) {

if (item == 5) {  

  array.push (6);

 };

})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接