首页 文章

在javascript中执行foreach时是否可以更改数组的值?

提问于
浏览
184

例:

var arr = ["one","two","three"];

arr.forEach(function(part){
  part = "four";
  return "four";
})

alert(arr);

数组仍然是它的原始值,有没有办法从迭代函数写入数组的元素?

8 回答

  • 2

    Javascript是按值传递的,这实质上意味着 part 是数组中值的副本 .

    要更改值,请在循环中访问数组本身 .

    arr[index] = 'new value';

  • 292

    要完全添加或删除会改变索引的元素,通过扩展zhujy_8833 slice()的建议迭代副本,只需计算已删除或添加的元素数量并相应地更改索引 . 例如,要删除元素:

    let values = ["A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8"];
    let count = 0;
    values.slice().forEach((value, index) => {
        if (value === "A2" || value === "A5") {
            values.splice(index - count++, 1);
        };
    });
    console.log(values);
    
    // Expected: [ 'A0', 'A1', 'A3', 'A4', 'A6', 'A7', 'A8' ]
    

    要在之前插入元素:

    if (value === "A0" || value === "A6" || value === "A8") {
        values.splice(index - count--, 0, 'newVal');
    };
    
    // Expected: ['newVal', A0, 'A1', 'A2', 'A3', 'A4', 'A5', 'newVal', 'A6', 'A7', 'newVal', 'A8' ]
    

    要在以下后插入元素:

    if (value === "A0" || value === "A6" || value === "A8") {
        values.splice(index - --count, 0, 'newVal');
    };
    
    // Expected: ['A0', 'newVal', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'newVal', 'A7', 'A8', 'newVal']
    

    要替换元素:

    if (value === "A3" || value === "A4" || value === "A7") {
        values.splice(index, 1, 'newVal');
    };
    
    // Expected: [ 'A0', 'A1', 'A2', 'newVal', 'newVal', 'A5', 'A6', 'newVal', 'A8' ]
    

    注意:如果同时实现'before'和'after'插入,代码应首先处理'before'插入,其他方式不会如预期

  • 99

    .forEach函数可以有一个回调函数(eachelement,elementIndex)所以基本上你需要做的是:

    arr.forEach(function(element,index){
        arr[index] = "four";   //set the value  
    });
    console.log(arr); //the array has been overwritten.
    

    或者,如果要保留原始数组,可以在执行上述过程之前复制它 . 要制作副本,您可以使用:

    var copy = arr.slice();
    
  • 0

    回调传递元素,索引和数组本身 .

    arr.forEach(function(part, index, theArray) {
      theArray[index] = "hello world";
    });
    

    编辑 - 如注释中所述, .forEach() 函数可以采用第二个参数,该参数将在每次调用回调时用作 this 的值:

    arr.forEach(function(part, index) {
      this[index] = "hello world";
    }, arr); // use arr as this
    

    第二个示例显示 arr 本身在回调中被设置为 this . 有人可能认为 .forEach() 调用中涉及的数组可能是 this 的默认值,但无论出于何种原因,它都不是;如果没有提供第二个参数, this 将为 undefined .

    另外重要的是要记住,在Array原型上提供了一整套类似的实用程序,Stackoverflow上有很多关于一个或另一个函数的问题,因此最好的解决方案就是选择一个不同的工具 . 你有:

    • forEach 用于对数组中的每个条目执行操作;

    • filter 用于生成仅包含限定条目的新数组;

    • map 用于通过转换现有数组来创建一对一的新数组;

    • some 检查数组中是否至少有一个元素符合某些描述;

    • every 检查数组中的所有条目是否与描述匹配;

    • find 在数组中查找值

    等等 . MDN link

  • 11

    用数组的索引替换它 .

    array[index] = new_value;
    
  • 62

    使用Array对象方法,您可以修改Array内容,但与基本for循环相比,这些方法缺少一个重要功能 . 您无法在运行时修改索引 .

    例如,如果要删除当前元素并将其放置在同一个数组中的另一个索引位置,则可以轻松执行此操作 . 如果将当前元素移动到先前位置,则在下一次迭代中没有问题,您将获得相同的下一个项目,就像您没有做任何事情一样 .

    考虑这个代码,我们将索引位置5的项目移动到索引位置2,一旦索引计数到5 .

    var ar = [0,1,2,3,4,5,6,7,8,9];
    ar.forEach((e,i,a) => {
    i == 5 && a.splice(2,0,a.splice(i,1)[0])
    console.log(i,e);
    }); // 0 0 - 1 1 - 2 2 - 3 3 - 4 4 - 5 5 - 6 6 - 7 7 - 8 8 - 9 9
    

    但是,如果我们将当前元素移动到当前索引位置之外的某个位置,事情就会变得有些混乱 . 然后,下一个项目将转移到移动的项目位置,在下一次迭代中,我们将无法查看或评估它 .

    考虑这个代码,我们将索引位置5处的项目移动到索引位置7,一旦索引计数到5 .

    var a = [0,1,2,3,4,5,6,7,8,9];
    a.forEach((e,i,a) => {
    i == 5 && a.splice(7,0,a.splice(i,1)[0])
    console.log(i,e);
    }); // 0 0 - 1 1 - 2 2 - 3 3 - 4 4 - 5 5 - 6 7 - 7 5 - 8 8 - 9 9
    

    所以我们从来没有在循环中遇到过6 . 通常在for循环中,当向前移动数组项时,预期会减小索引值,以便索引在下一次运行中保持在相同位置,并且仍然可以评估移动到已移除项目位置的项目 . 这对阵列方法是不可能的 . 你不能改变索引 . 检查以下代码

    var a = [0,1,2,3,4,5,6,7,8,9];
    a.forEach((e,i,a) => {
    i == 5 && (a.splice(7,0,a.splice(i,1)[0]), i--);
    console.log(i,e);
    }); // 0 0 - 1 1 - 2 2 - 3 3 - 4 4 - 4 5 - 6 7 - 7 5 - 8 8 - 9 9
    

    正如你所看到的那样,当我们减少 i 时,它将不会从5,而是从它离开的地方继续 .

    所以请记住这一点 .

  • 1

    让我们试着保持简单,并讨论它是如何工作的 . 它与变量类型和函数参数有关 .

    这是我们正在讨论的代码:

    var arr = ["one","two","three"];
    
    arr.forEach(function(part) {
      part = "four";
      return "four";
    })
    
    alert(arr);
    

    首先,这里是您应该阅读的有关Array.prototype.forEach()的内容:

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

    其次,让我们简单地谈谈JavaScript中的值类型 .

    Primitives (undefined,null,String,Boolean,Number)存储实际值 .

    例如: var x = 5;

    Reference Types (自定义对象)存储对象的内存位置 .

    例如: var xObj = { x : 5 };

    第三,函数参数如何工作 .

    在函数中,参数按值传递 always .

    因为 arr 是一个字符串数组,它是一个 primitive 对象的数组,这意味着它们是按值存储的 .

    因此,对于上面的代码,这意味着每次forEach()迭代时, part 等于与 arr[index] 相同的值, but not the same object .

    part = "four"; 将更改 part 变量,但将单独留下 arr .

    以下代码将更改您想要的值:

    var arr = ["one","two","three"];
    
    arr.forEach(function(part, index) {
      arr[index] = "four";
    });
    
    alert(arr);
    

    现在,如果array arrreference types 的数组,则以下代码将起作用,因为引用类型存储对象的内存位置而不是实际对象 .

    var arr = [{ num : "one" }, { num : "two"}, { num : "three"}];
    
    arr.forEach(function(part, index) {
      // part and arr[index] point to the same object
      // so changing the object that part points to changes the object that arr[index] points to
    
      part.num = "four";
    });
    
    alert(arr[0].num);
    alert(arr[1].num);
    alert(arr[2].num);
    

    以下说明您可以将 part 更改为指向新对象,同时将对象保留在 arr 中:

    var arr = [{ num : "one" }, { num : "two"}, { num : "three"}];
    
    arr.forEach(function(part, index) {
      // the following will not change the object that arr[index] points to because part now points at a new object
      part = 5;
    });
    
    alert(arr[0].num);
    alert(arr[1].num);
    alert(arr[2].num);
    
  • 2

    数组: ["1", 2, 3, 4]
    结果: ["foo1", "foo2", "foo3", "foo4"]

    Array.prototype.map()保留原始数组

    通过引入新变量 modifiedArr 实现

    var arr = ["1", 2, 3, 4];
    
    var modifiedArr = arr.map(function(v) {
      return "foo"+ v;
    });
    
    console.log( "Original:", arr );
    console.log( "Modified:", modifiedArr );
    

    Array.prototype.map()修改原始数组

    通过重新分配 arr 变量来实现

    var arr = ["1", 2, 3, 4];
    
    arr = arr.map(function(v) {
      return "foo"+ v;
    });
    
    console.log( arr );
    

    Array.prototype.forEach()修改原始数组

    通过索引 arr[i] 定位它的键来实现

    var arr = ["1", 2, 3, 4];
    
    arr.forEach(function(v, i) {
       arr[i] = "foo" + v;
    });
    
    console.log( "Original:", arr );
    

相关问题