J'essaye de modifier un tableau copié sans changer l'original. C'est ce que j'ai essayé, en utilisant la méthode slice () , mais cela ne fonctionne pas comme prévu:
//toFill holds the values I want to add into an array named secondArr,
//replace every empty sting within secondArr with 0
var toFill = [0, 0, 0, 0];
var mainArr = [
[" ", 1, 1, 1],
[" ", 1, 1, 1],
[" ", 1, 1, 1],
[" ", 1, 1, 1]
];
var secondArr = mainArr.slice(0,4);
//this function returns a 1D array, stores the indices of all empty strings within an array
function findBlankSpaces(secondArr) {
var emptyIndices = [];
var innerArrLen = secondArr.length;
var outterArrLen = secondArr[0].length;
for (var i = 0; i < innerArrLen; i++) {
for (var j = 0; j < outterArrLen; j++) {
if (secondArr[i][j] == " ") {
emptyIndices.push([i, j]);
}
}
}
return emptyIndices;
}
//this function returns the modified array, with empty spaces replaced with 0s
function fillWithZero(secondArr, toFill) {
var emptyIndices = findBlankSpaces(secondArr);
for (var i = 0; i < emptyIndices.length; i++) {
secondArr[emptyIndices[i][0]][emptyIndices[i][1]] = toFill[i];
}
}
//consoles
console.log(fillWithZero(secondArr, toFill));
console.log(mainArr);
//expected output in console is [[" ", 1,1,1], [" ",1,1,1], [" ",1,1,1], [" ",1,1,1]];
//actual output is [[0,1,1,1], [0,1,1,1], [0,1,1,1], [0,1,1,1]];
//I didn't modify mainArr, but only modified secondArr, why that mainArr also affected?
Je n'ai pas modifié le mainArr , j'ai uniquement créé une copie en utilisant slice () , mais pourquoi il garde changer quand sa copie change?
Cette question est: Tout moyen d'empêcher que cela se produise ou comment appeler à nouveau le mainArr sans aucun 0 dedans, je veux que mainArr reste inchangé. Merci
5 Réponses :
Comme indiqué sur Slice MDN , la méthode slice renvoie une copie superficielle du tableau qui l'appelle. Deep Copy en présente quelques-uns façons de copier en profondeur des objets dans JS. Un bon qu'il mentionne est
var secondArr = JSON.parse(JSON.stringify(mainArr))
Cela convertit votre tableau en JSON, puis l'analyse en un nouvel objet
Array et object ont toujours une référence au parent lorsqu'une copie est faite.
C'est à ce moment-là que nous copions le tableau a dans le tableau b , les modifications apportées au tableau b affectent également le tableau a car b fait référence à a .
Pour résoudre ce problème, nous pouvons utiliser l'opérateur de propagation (...)
veuillez vérifier l'extrait de code ci-dessous
var a = [1,2,3,4,5,6];
var b = a;
console.log('First array ', a);
console.log('Second array ', b);
// lets remove an element from b and check
b.splice(1,1);
console.log('Second array after splicing', b);
console.log('First array after splicing', a);
// Here value in the index 1 is missing in both the array.
// to prevent this we can use spread operator
var a = [1,2,3,4,5,6];
var b = [...a];
console.log('First array ', a);
console.log('Second array ', b);
// lets remove an element from b and check
b.splice(1,1);
console.log('Second array after splicing using spread operator', b);
console.log('First array after splicing using spread operator', a);
Il est important de noter que l'opérateur de diffusion ... fera également des copies superficielles uniquement. vous pouvez voir un exemple ici stackoverflow.com/questions/54605286/...
La méthode slice () renvoie une copie superficielle d'une partie d'un tableau dans un nouvel objet tableau
Le mot clé ici est shallow.
mainArr est un tableau de tableaux, donc alors que slice code> vous donnera une nouvelle copie du tableau externe, le tableau qu'il vous donne contient des références aux éléments de mainArray donc lorsque vous les modifiez, vous modifiez en fait les éléments de mainArray code>.
Vous pouvez cloner en profondeur mainArr, mais il sera probablement plus efficace de ne remplacer que les bits dont vous avez besoin.
Cela fonctionne, même si cela peut être rendu plus propre. Une option serait d'utiliser immer pour effectuer les modifications.
p >
//replace every empty sting within secondArr with 0
var toFill = [0, 0, 0, 0];
var mainArr = [[" ", 1, 1, 1], [" ", 1, 1, 1], [" ", 1, 1, 1], [" ", 1, 1, 1]];
//this function returns a 1D array, stores the indices of all empty strings within an array
function findBlankSpaces(arr) {
var emptyIndices = [];
var innerArrLen = arr.length;
var outterArrLen = arr[0].length;
for (var i = 0; i < innerArrLen; i++) {
for (var j = 0; j < outterArrLen; j++) {
if (arr[i][j] == " ") {
emptyIndices.push([i, j]);
}
}
}
return emptyIndices;
}
//this function returns the modified array, with empty spaces replaced with 0s
function fillWithZero(mainArr, toFill) {
var emptyIndices = findBlankSpaces(mainArr);
let newArr = [...mainArr];
emptyIndices.forEach(indic => {
newArr[indic[0]] = [
...mainArr[indic[0]].slice(0, indic[1]),
toFill[indic[1]],
...mainArr[indic[0]].slice(indic[1] + 1)
];
});
return newArr;
}
//consoles
console.log(fillWithZero(mainArr, toFill));
console.log(mainArr);
Si vous appliquez la méthode slice à un tableau qui contient des tableaux, les sous-tableaux sont copiés par référence. Tout ce que vous ajoutez à la copie sera ajouté au tableau d'origine contenant les tableaux.
La méthode slice () retourne une copie superficielle d'une partie d'un tableau dans un nouvel objet tableau sélectionné du début à la fin (fin non incluse) où le début et la fin représentent l'index des éléments de ce tableau. Le tableau d'origine ne sera pas modifié.
La méthode slice () renvoie une copie superficielle d'une partie d'un tableau dans un nouvel objet tableau sélectionné du début à la fin (fin non incluse) où le début et la fin représentent l'index des éléments de ce tableau. Le tableau d'origine ne sera pas modifié.
Veuillez consulter ce lien:
"Je n'ai pas modifié le mainArr , j'ai seulement créé une copie en utilisant slice (), mais pourquoi il continue de changer quand sa copie change?" Reportez-vous à
.slice () < / code>: "La méthode slice () renvoie une copie superficielle d'une partie d'un tableau dans un nouvel objet tableau sélectionné du début à la fin (fin non incluse). Le tableau d'origine ne sera pas modifié." Vous devez spécifier l'index (arr.slice ([begin [ end]]))tableau et objet ont toujours une référence au parent lorsqu'une copie est effectuée. donc chaque fois qu'un changement se produit, il affectera
Faites ceci:
var secondArr = JSON.parse (JSON.stringify (mainArr));