是否有可能改变数组的值在foreach中的JavaScript?

例:

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

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

callback传递元素,索引和数组本身。

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

让我们尽量保持简单,并讨论它是如何工作的。 它与variablestypes和函数参数有关。

这里是你的代码,我们正在谈论:

 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中的值types。

基元 (undefined,null,String,Boolean,Number)存储一个实际的值。

例如: var x = 5;

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

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

第三,function参数是如何工作的。

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

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

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

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

以下代码将更改您所需的值:

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

现在,如果数组arr引用types的数组,下面的代码将工作,因为引用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); 

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

1.使用Array.prototype.map() MDN保留原始数组:

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

Javascript是通过值传递的,其实质上意味着part是数组中的值的副本

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

arr[index] = 'new value';

将其replace为数组的索引。

 array[index] = new_value; 

.forEach函数可以有一个callback函数(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(); 

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

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

考虑到这个代码,我们将索引位置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 

正如你所看到的,当我们递减的时候,它不会从5到6继续下去。

所以记住这一点。