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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12482961/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 10:29:53  来源:igfitidea点击:

is it possible to change values of the array when doing foreach in javascript?

javascriptarraysforeachpass-by-reference

提问by rsk82

example:

例子:

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

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

alert(arr);

The array is still with it's original values, is there any way to have writing access to array's elements from iterating function ?

数组仍然具有它的原始值,有什么方法可以从迭代函数中写入对数组元素的访问?

回答by Pointy

The callback is passed the element, the index, and the array itself.

回调传递元素、索引和数组本身。

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

edit— as noted in a comment, the .forEach()function can take a second argument, which will be used as the value of thisin each call to the callback:

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

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

That second example shows arritself being set up as thisin the callback.One might think that the array involved in the .forEach()call might be the defaultvalue of this, but for whatever reason it's not; thiswill be undefinedif that second argument is not provided.

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

(Note: the above stuff about thisdoes not apply if the callback is a =>function, because thisis never bound to anything when such functions are invoked.)

(注意:this如果回调是=>函数,则上述内容不适用,因为this在调用此类函数时永远不会绑定到任何内容。)

Also it's important to remember that there is a whole family of similar utilities provided on the Array prototype, and many questions pop up on Stackoverflow about one function or another such that the best solution is to simply pick a different tool. You've got:

同样重要的是要记住,Array 原型上提供了一整套类似的实用程序,并且 Stackoverflow 上会弹出许多关于一个或另一个函数的问题,因此最好的解决方案是简单地选择一个不同的工具。你有:

  • forEachfor doing a thing with or to every entry in an array;
  • filterfor producing a new array containing only qualifying entries;
  • mapfor making a one-to-one new array by transforming an existing array;
  • someto check whether at least one element in an array fits some description;
  • everyto check whether allentries in an array match a description;
  • findto look for a value in an array
  • forEach用于对数组中的每个条目进行处理;
  • filter用于生成仅包含符合条件的条目的新数组;
  • map用于通过转换现有数组来制作一对一的新数组;
  • some检查数组中是否至少有一个元素符合某种描述;
  • every检查数组中的所有条目是否与描述匹配;
  • find在数组中查找值

and so on. MDN link

等等。MDN链接

回答by Dave

Let's tryto keep it simple and discuss how it is actually working. It has to do with variable types and function parameters.

让我们尽量保持简单并讨论它是如何实际工作的。它与变量类型和函数参数有关。

Here is your code we are talking about:

这是我们正在谈论的您的代码:

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

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

alert(arr);

First off, here is where you should be reading about Array.prototype.forEach():

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

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

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

Second, let's talk briefly about value types in JavaScript.

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

Primitives(undefined, null, String, Boolean, Number) store an actual value.

原语(未定义、空值、字符串、布尔值、数字)存储实际值。

ex: var x = 5;

前任: var x = 5;

Reference Types(custom objects) store the memory location of the object.

引用类型(自定义对象)存储对象的内存位置。

ex: var xObj = { x : 5 };

前任: var xObj = { x : 5 };

And third, how function parameters work.

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

In functions, parameters are alwayspassed by value.

在函数中,参数总是按值传递。

Because arris an array of Strings, it's an array of primitiveobjects, which means they are stored by value.

因为arr是一个字符串数组,所以它是一个原始对象数组,这意味着它们是按值存储的。

So for your code above, this means that each time the forEach() iterates, partis equal to the same value as arr[index], but not the same object.

因此,对于上面的代码,这意味着每次 forEach() 迭代时,part都等于与 相同的值arr[index]但不是相同的对象

part = "four";will change the partvariable, but will leave arralone.

part = "four";会改变part变量,但会离开arr

The following code will change the values you desire:

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

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

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

alert(arr);

Now if array arrwas an array of reference types, the following code will work because reference types store a memory location of an object instead of the actual object.

现在如果 arrayarr是一个引用类型数组,下面的代码将起作用,因为引用类型存储对象的内存位置而不是实际对象。

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);

The following illustrates that you can change partto point to a new object while leaving the objects stored in arralone:

下图说明您可以更改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);

回答by Roko C. Buljan

Array: [1, 2, 3, 4]
Result: ["foo1", "foo2", "foo3", "foo4"]

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

Array.prototype.map()Keep original array

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

const originalArr = ["Iron", "Super", "Ant", "Aqua"];
const modifiedArr = originalArr.map(name => `${name}man`);

console.log( "Original: %s", originalArr );
console.log( "Modified: %s", modifiedArr );

Array.prototype.forEach()Override original array

Array.prototype.forEach()覆盖原始数组

const originalArr = ["Iron", "Super", "Ant", "Aqua"];
originalArr.forEach((name, index) => originalArr[index] = `${name}man`);

console.log( "Overridden: %s", originalArr );

回答by hvgotcodes

Javascript is pass by value, and which essentially means partis a copyof the value in the array.

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

To change the value, access the array itself in your loop.

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

arr[index] = 'new value';

arr[index] = 'new value';

回答by Asif Alamgir

replace it with index of the array.

用数组的索引替换它。

array[index] = new_value;

回答by J. Peterson

Here's a similar answer using using a =>style function:

这是使用=>样式函数的类似答案:

var data = [1,2,3,4];
data.forEach( (item, i, self) => self[i] = item + 10 );

gives the result:

给出结果:

[11,12,13,14]

The selfparameter isn't strictly necessary with the arrow style function, so

self参数不与箭头样式功能绝对必要的,所以

data.forEach( (item,i) => data[i] = item + 10);

also works.

也有效。

回答by zhujy_8833

The .forEach function can have a callback function(eachelement, elementIndex) So basically what you need to do is :

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

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

Or if you want to keep the original array, you can make a copy of it before doing the above process. To make a copy, you can use:

或者如果你想保留原来的数组,你可以在做上述过程之前复制一份。要制作副本,您可以使用:

var copy = arr.slice();

回答by Redu

With the Array object methods you can modify the Array content yet compared to the basic for loops, these methods lack one important functionality. You can not modify the index on the run.

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

For example if you will remove the current element and place it to another index position within the same array you can easily do this. If you move the current element to a previous position there is no problem in the next iteration you will get the same next item as if you hadn't done anything.

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

Consider this code where we move the item at index position 5 to index position 2 once the index counts up to 5.

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

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

However if we move the current element to somewhere beyond the current index position things get a little messy. Then the very next item will shift into the moved items position and in the next iteration we will not be able to see or evaluate it.

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

Consider this code where we move the item at index position 5 to index position 7 once the index counts up to 5.

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

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

So we have never met 6 in the loop. Normally in a for loop you are expected decrement the index value when you move the array item forward so that your index stays at the same position in the next run and you can still evaluate the item shifted into the removed item's place. This is not possible with array methods. You can not alter the index. Check the following code

所以我们从未在循环中遇到过 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

As you see when we decrement iit will not continue from 5 but 6, from where it was left.

正如你看到的,当我们递减i它时,它不会从 5 继续,而是从它离开的地方 6 开始。

So keep this in mind.

所以请记住这一点。

回答by Leigh Mathieson

To add or delete elements entirely which would alter the index, by way of extension of zhujy_8833 suggestion of slice() to iterate over a copy, simply count the number of elements you have already deleted or added and alter the index accordingly. For example, to delete elements:

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

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' ]

To insert elements before:

在之前插入元素:

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' ]

To insert elements after:

在之后插入元素:

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']

To replace an element:

替换元素:

if (value === "A3" || value === "A4" || value === "A7") {
    values.splice(index, 1, 'newVal');
};

// Expected: [ 'A0', 'A1', 'A2', 'newVal', 'newVal', 'A5', 'A6', 'newVal', 'A8' ]

Note: if implementing both 'before' and 'after' inserts, code should handle 'before' inserts first, other way around would not be as expected

注意:如果同时实现 'before' 和 'after' 插入,代码应该首先处理 'before' 插入,否则不会像预期的那样

回答by Shuhad zaman

You can try this if you want to override

如果你想覆盖,你可以试试这个

var newArray= [444,555,666];
var oldArray =[11,22,33];
oldArray.forEach((name, index) => oldArray [index] = newArray[index]);
console.log(newArray);