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
is it possible to change values of the array when doing foreach in javascript?
提问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 this
in 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 arr
itself being set up as this
in 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; this
will be undefined
if that second argument is not provided.
第二个例子显示arr
它自己是this
在回调中设置的。有人可能认为.forEach()
调用中涉及的数组可能是 的默认值this
,但无论出于何种原因,它都不是;this
会undefined
如果没有提供第二个参数。
(Note: the above stuff about this
does not apply if the callback is a =>
function, because this
is 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 上会弹出许多关于一个或另一个函数的问题,因此最好的解决方案是简单地选择一个不同的工具。你有:
forEach
for doing a thing with or to every entry in an array;filter
for producing a new array containing only qualifying entries;map
for making a one-to-one new array by transforming an existing array;some
to check whether at least one element in an array fits some description;every
to check whether allentries in an array match a description;find
to 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 arr
is 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, part
is equal to the same value as arr[index]
, but not the same object.
因此,对于上面的代码,这意味着每次 forEach() 迭代时,part
都等于与 相同的值arr[index]
,但不是相同的对象。
part = "four";
will change the part
variable, but will leave arr
alone.
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 arr
was 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 part
to point to a new object while leaving the objects stored in arr
alone:
下图说明您可以更改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 part
is 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 self
parameter 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 i
it 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);