zmiana wartości w tablicy podczas wykonywania foreach

Przykład:

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

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

alert(arr);

Tablica jest nadal z oryginalnymi wartościami, czy jest jakiś sposób, aby mieć dostęp do zapisu elementów tablicy z funkcji iteracyjnej ?

Author: Roko C. Buljan, 2012-09-18

10 answers

Wywołanie zwrotne przekazuje element, indeks i samą tablicę.

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

edit - jak zaznaczono w komentarzu, funkcja .forEach() może przyjmować drugi argument, który będzie użyty jako wartość this w każdym wywołaniu wywołania zwrotnego:

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

Ten drugi przykład pokazuje, że arr sama jest ustawiona jako this w wywołaniu zwrotnym.Można by pomyśleć, że tablica biorąca udział w wywołaniu .forEach() może być wartością domyślną Z this, ale z jakiegokolwiek powodu nie jest; this będzie undefined, Jeśli ten drugi argument nie zostanie podany.

(uwaga: powyższe informacje o this nie mają zastosowania, jeśli wywołanie zwrotne jest funkcją =>, ponieważ this nigdy nie jest z niczym związane, gdy takie funkcje są wywoływane.)

Ważne jest również, aby pamiętać, że istnieje cała rodzina podobnych narzędzi dostarczanych w prototypie tablicy, a wiele pytań pojawia się na Stackoverflow na temat jednej lub drugiej funkcji, tak że najlepszym rozwiązaniem jest po prostu wybrać inną narzędzie. Masz:

  • forEach do robienia rzeczy z lub do każdego wpisu w tablicy;
  • filter do tworzenia nowej tablicy zawierającej tylko kwalifikujące się wpisy;
  • Do tworzenia nowej tablicy jeden do jednego poprzez przekształcenie istniejącej tablicy;
  • some aby sprawdzić, czy przynajmniej jeden element w tablicy pasuje do jakiegoś opisu;
  • every aby sprawdzić, czy wszystkie wpisy w tablicy pasują do opisu;
  • find szukać wartości w tablicy

I tak dalej. MDN link

 533
Author: Pointy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-10 22:01:16

Spróbujmy uprościć to i omówić, jak to naprawdę działa. Ma to związek z typami zmiennych i parametrami funkcji.

Oto twój kod, o którym mówimy:

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

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

alert(arr);

Po pierwsze, tutaj powinieneś przeczytać o tablicy.prototyp.forEach ():

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

Po Drugie, porozmawiajmy krótko o typach wartości w JavaScript.

Primitives (undefined, null, String, Boolean, Number) przechowuje rzeczywistą wartość.

Ex: var x = 5;

Typy referencji (obiekty niestandardowe) przechowują położenie obiektu w pamięci.

Ex: var xObj = { x : 5 };

I po trzecie, jak działają parametry funkcji.

W funkcjach parametry są zawsze przekazywane przez wartość.

Ponieważ arr jest tablicą łańcuchów, jest tablicą prymitywnych obiektów, które oznacza, że są one przechowywane według wartości.

Zatem dla powyższego kodu oznacza to, że za każdym razem, gdy foreach() iteruje, part jest równa tej samej wartości, co arr[index], ale nie ten sam obiekt .

part = "four"; zmieni zmienną part, ale pozostawi arr w spokoju.

Poniższy kod zmieni pożądane wartości:

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

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

alert(arr);

Teraz, jeśli tablica arr Była tablicą typów referencyjnych , poniższy kod będzie działał, ponieważ typy referencyjne przechowują pamięć lokalizacja obiektu zamiast rzeczywistego obiektu.

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

Poniższe ilustracje pokazują, że można zmienić part, aby wskazać nowy obiekt, pozostawiając tylko obiekty przechowywane w 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);
 141
Author: Dave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-08 16:23:27

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

Array.prototype.map() Zachowaj oryginalną tablicę

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 oryginalna tablica

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

console.log( "Overridden: %s", originalArr );
 108
Author: Roko C. Buljan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Javascript jest przekazywana przez wartość, co zasadniczo oznacza, że part jest kopią wartości w tablicy.

Aby zmienić wartość, uzyskaj dostęp do tablicy w pętli.

arr[index] = 'new value';

 15
Author: hvgotcodes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-18 18:38:02

Oto podobna odpowiedź za pomocą funkcji => style:

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

Daje wynik:

[11,12,13,14]

Parametr self nie jest ściśle konieczny dla funkcji stylu strzałki, więc

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

Również działa.

 6
Author: J. Peterson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-27 23:56:04

Zastąp go indeksem tablicy.

array[index] = new_value;
 3
Author: Asif Alamgir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-18 18:39:54

The .funkcja forEach może mieć funkcję zwrotną (eachelement, elementIndex) Więc w zasadzie to co musisz zrobić to:

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

Lub jeśli chcesz zachować oryginalną tablicę, możesz zrobić jej kopię przed wykonaniem powyższego procesu. Aby zrobić kopię, możesz użyć:

var copy = arr.slice();
 3
Author: zhujy_8833,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-18 23:17:52

Za pomocą metod obiektu Array można modyfikować zawartość tablicy, jednak w porównaniu do pętli basic for metody te nie posiadają jednej ważnej funkcjonalności. Nie można modyfikować indeksu podczas biegu.

Na przykład, jeśli usuniesz bieżący element i umieścisz go w innej pozycji indeksu w tej samej tablicy, możesz to łatwo zrobić. Jeśli przeniesiesz bieżący element do poprzedniej pozycji, nie będzie problemu w następnej iteracji, otrzymasz ten sam następny element, tak jak gdybyś tego nie zrobił cokolwiek.

Rozważ ten kod, w którym przesuwamy element na pozycji indeksu 5 do pozycji indeksu 2, gdy indeks liczy się do 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

Jednakże, jeśli przeniesiemy bieżący element gdzieś poza bieżącą pozycję indeksu, sprawy będą trochę brudne. Następnie następny element przesunie się na pozycję przesuniętych elementów i w następnej iteracji nie będziemy mogli go zobaczyć ani ocenić.

Rozważmy ten kod, w którym przesuwamy element na pozycji indeksu 5 do pozycji indeksu 7 raz indeks liczy do 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

Więc nigdy nie spotkaliśmy 6 W pętli. Zwykle w pętli for spodziewane jest zmniejszenie wartości indeksu podczas przesuwania elementu tablicy do przodu, tak aby indeks pozostał na tej samej pozycji w następnym uruchomieniu i nadal można ocenić element przeniesiony na miejsce usuniętego elementu. Nie jest to możliwe przy metodach tablicowych. Nie można zmienić indeksu. Sprawdź następujący kod

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

Jak widzisz, kiedy spadamy i to nie będzie kontynuowane od 5 / align = "left" /

Więc miej to na uwadze.
 2
Author: Redu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-15 18:23:41

Aby dodać lub usunąć elementy, które całkowicie zmieniłyby indeks, poprzez rozszerzenie zhujy_8833 sugestii slice() do iteracji nad kopią, po prostu policz liczbę elementów, które już usunąłeś lub dodałeś i odpowiednio zmodyfikuj indeks. Na przykład, aby usunąć elementy:

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

Wstawianie elementów przed:

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

Wstawianie elementów Po:

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

Aby zastąpić element:

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

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

Uwaga: Jeśli zaimplementowano zarówno wstawki "przed", jak i "po", Kod należy najpierw obsługiwać wstawki "przed", w przeciwnym razie nie będzie tak, jak oczekiwano

 2
Author: Leigh Mathieson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-19 11:36:11

Możesz spróbować, jeśli chcesz obejść

var newArray= [444,555,666];
var oldArray =[11,22,33];
oldArray.forEach((name, index) => oldArray [index] = newArray[index]);
console.log(newArray);
 0
Author: Shuhad zaman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-12 11:36:08