在循环时修改数组是否安全?

时间:2013-11-01 04:31:34

标签: javascript underscore.js

在循环时修改数组是否安全,例如推送元素?

我正在使用下划线每个方法

2 个答案:

答案 0 :(得分:1)

我不确定你的意思是安全的,但你必须有充分的理由去做。我玩了一下,这就是我得到的:

_.each(a, function(el) { 
    if (el % 2 == 0) 
        a.push(el + 1); 
    console.log(el); 
});

// logs 1, 2, 3, 4, 5

console.log(a);
// logs [ 1, 2, 3, 4, 5, 3, 5 ]

在这种情况下,除非您想要查看添加的元素,否则不存在负面影响,但如果您要更改特定元素,则可能会发现自己处于棘手的情况:

_.each(a, function(el, index) { 
    a[index + 1] = el - 1;
    if (el % 2 == 0) 
        a.push(el + 1); 
    console.log(el); 
});

// logs 1, 0, -1, -2, -3

对大多数用例使用_.map会更有意义。

答案 1 :(得分:1)

我建议避免使用each,除非您绝对需要为集合中的每个项目产生副作用(触发事件,打印结果等)。只需修改您的收藏,就有更好的方法。

如果每个添加的元素只是单个输入元素的结果,那么典型的函数模式将是flatmap数组,可以考虑两个步骤:

  1. 使用map应用一个函数,该函数为每个元素生成一个数组作为结果。整体结果将是一个数组数组。
  2. 在该数组数组上使用flatten来获取一维数组。
  3. 使用underscorelodash

    var origArray = [1, 2, 3, 4];
    var duplicateIf3 = function (val) { return val === 3 ? [val, val] : val; };
    _.flatten(origArray.map(duplicateIf3));
    // -> [1, 2, 3, 3, 4]
    

    (在类型FP中,对于非3的值,函数必须返回[val],但是flatten并不关心 - 它会将您提供的任何内容展平为一维。)

    如果新元素依赖于它之前的所有元素,那么您可能会使用reducefold代替,将空数组作为初始值。

    var origArray = [1, 2, 3, 4];
    origArray.reduce(function (acc, val) { return acc.concat(acc).concat(val); }, []);
    // -> [1, 1, 2, 1, 1, 2, 3, 1, 1, 2, 1, 1, 2, 3, 4]
    

    (对不起,我想不出一个现实的例子,但是这里每一步都以一种非常简单的方式使用所有前面步骤的完整输出用于说明目的,你可以从原始数组的每个值看到发生了什么另请注意,如果您不想使用下划线/ Lodash,可以从flatten创建自己的reduce

    reduceflatmap更通用,但是这两种方法都能够将数组转换为更大的数组,其中一些数据取决于第一个数组。

    如果您有兴趣了解更多相关信息,我强烈建议您查看Reg Braithwaite的免费(在线)Javascript Allongé