web-dev-qa-db-fra.com

quelle utilisation a la méthode javascript forEach (que la carte ne peut pas faire)?

La seule différence que je vois dans map et foreach est que map renvoie un tableau et que forEach ne l’est pas. Cependant, je ne comprends même pas la dernière ligne de la méthode forEach "func.call(scope, this[i], i, this);". Par exemple, "this" et "scope" ne font-ils pas référence au même objet et this[i] et i ne font-ils pas référence à la valeur actuelle de la boucle?

J'ai remarqué dans un autre message que quelqu'un disait: "Utilisez forEach lorsque vous voulez faire quelque chose sur la base de chaque élément de la liste. Vous pourriez par exemple ajouter des éléments à la page. En gros, c'est génial lorsque vous voulez des" effets secondaires ". Je ne sais pas ce que l’on entend par effets secondaires. 

Array.prototype.map = function(fnc) {
    var a = new Array(this.length);
    for (var i = 0; i < this.length; i++) {
        a[i] = fnc(this[i]);
    }
    return a;
}

Array.prototype.forEach = function(func, scope) { 
    scope = scope || this; 
    for (var i = 0, l = this.length; i < l; i++) {
        func.call(scope, this[i], i, this); 
    } 
}

Enfin, existe-t-il de véritables utilisations de ces méthodes en javascript (puisque nous ne mettons pas à jour une base de données) autres que de manipuler des nombres comme celui-ci:

alert([1,2,3,4].map(function(x){ return x + 1})); //this is the only example I ever see of map in javascript.

Merci pour toute réponse.

85
JohnMerlino

La différence essentielle entre map et forEach dans votre exemple est que forEach agit sur les éléments de tableau d'origine, alors que map renvoie explicitement un nouveau tableau. 

Avec forEach, vous prenez des mesures avec - et modifiez éventuellement - chaque élément du tableau d'origine. La méthode forEach exécute la fonction fournie pour chaque élément mais ne renvoie rien (undefined). Par contre, map parcourt le tableau, applique une fonction à chaque élément et émet le résultat sous la forme d'un nouveau tableau

L'effet secondaire avec forEach est que le tableau d'origine est en cours de modification. "Aucun effet secondaire" avec map signifie que, dans un usage idiomatique, les éléments du tableau d'origine sont non modifiés; le nouveau tableau est un mappage un à un de chaque élément du tableau d'origine - la transformation de mappage étant votre fonction fournie.

Le fait qu'il n'y ait pas de base de données impliquée ne signifie pas que vous ne serez pas obligé d'opérer sur des structures de données, ce qui, après tout, est l'une des essences de la programmation dans n'importe quel langage. En ce qui concerne votre dernière question, votre tableau peut contenir non seulement des nombres, mais également des objets, des chaînes, des fonctions, etc.

90
Ken Redler

La principale différence entre les deux méthodes est conceptuelle et stylistique: vous utilisez forEach lorsque vous voulez faire quelque chose à ou avec chaque élément d'un tableau ("avec" est ce que le message que vous citez veut dire "effets secondaires", je pense), alors que vous utilisez map lorsque vous voulez copier et transformer chaque élément d'un tableau (sans changer l'original). 

Étant donné que map et forEach appellent tous deux une fonction sur chaque élément d'un tableau et que cette fonction est définie par l'utilisateur, vous ne pouvez pratiquement rien faire avec l'un et pas avec l'autre. Il est possible, bien que moche, d'utiliser map pour modifier un tableau sur place et/ou faire quelque chose avec des éléments de tableau:

var a = [{ val: 1 }, { val: 2 }, { val: 3 }];
a.map(function(el) {
    el.val++; // modify element in-place
    alert(el.val); // do something with each element
});
// a now contains [{ val: 2 }, { val: 3 }, { val: 4 }]

mais beaucoup plus propre et plus évident quant à votre intention d'utiliser forEach:

var a = [{ val: 1 }, { val: 2 }, { val: 3 }];
a.forEach(function(el) { 
    el.val++;
    alert(el.val);
});

Surtout si, comme c'est généralement le cas dans le monde réel, el est une variable lisible par l'homme: 

cats.forEach(function(cat) { 
    cat.meow(); // nicer than cats[x].meow()
});

De la même manière, vous pouvez facilement utiliser forEach pour créer un nouveau tableau:

var a = [1,2,3],
    b = [];
a.forEach(function(el) { 
    b.Push(el+1); 
});
// b is now [2,3,4], a is unchanged

mais c'est plus propre d'utiliser map:

var a = [1,2,3],
    b = a.map(function(el) { 
        return el+1; 
    });

Notez également que, étant donné que map crée un nouveau tableau, il risque de subir au moins un léger impact performance/mémoire lorsque vous avez uniquement besoin de l'itération, en particulier pour les grands tableaux - voir http://jsperf.com/map-foreach

En ce qui concerne les raisons pour lesquelles vous souhaitez utiliser ces fonctions, elles sont utiles chaque fois que vous devez manipuler des tableaux en javascript, ce qui est assez souvent (même si nous ne parlons que de javascript dans un environnement de navigateur), presque à tout moment. vous accédez à un tableau que vous n'écrivez pas manuellement dans votre code. Vous pourriez avoir affaire à un tableau d’éléments DOM de la page, à des données extraites d’une demande AJAX ou à des données entrées dans un formulaire par l’utilisateur. Un exemple courant que je rencontre est celui de l'extraction de données à partir d'une API externe, dans laquelle vous pouvez utiliser map pour transformer les données au format souhaité, puis utiliser forEach pour effectuer une itération sur votre nouveau tableau afin de l'afficher à votre utilisateur.

66
nrabinowitz

La réponse votée (de Ken Redler) est trompeuse. 

Un effet secondaire en informatique signifie qu'une propriété d'une fonction/méthode modifie un état global [wiki] . Dans un sens étroit, cela peut également inclure la lecture d'un état global, plutôt que d'arguments. Dans la programmation impérative ou OO, les effets secondaires apparaissent la plupart du temps. Et vous en utilisez probablement sans vous en rendre compte.

La différence significative entre forEach et map est que map alloue de la mémoire et stocke la valeur renvoyée, alors que forEach la jette. Voir emca spec pour plus d'informations.

En ce qui concerne la raison pour laquelle les gens disent que forEach est utilisé lorsque vous souhaitez un effet secondaire, c'est que la valeur de retour de forEach est toujours undefined. Si elle n'a pas d'effet secondaire (ne change pas l'état global), la fonction ne fait que perdre du temps CPU. Un compilateur optimiseur éliminera ce bloc de code et le remplacera par la valeur finale (undefined). 

Par ailleurs, il convient de noter que JavaScript n'a pas de restriction sur les effets secondaires. Vous pouvez toujours modifier le tableau d'origine dans map.

var a = [1,2,3]; //original
var b = a.map( function(x,i){a[i] = 2*x; return x+1} );
console.log("modified=%j\nnew array=%j",a,b);
// output:
// modified=[2,4,6]
// new array=[2,3,4]
13
Jack Tang

Vous pouvez utiliser map comme s'il s'agissait de forEach.

Il fera cependant plus que ce qu'il doit faire.

scope peut être un objet arbitraire; ce n'est en aucun cas nécessairement this.

Quant à savoir s’il existe des utilisations réelles pour les variables map et forEach, il convient également de demander s’il existe des utilisations réelles des boucles for ou while.

3
wombleton

Bien que toutes les questions précédentes soient correctes, je ferais certainement une distinction différente. L'utilisation de map et forEach peut impliquer une intention.

J'aime utiliser map lorsque je suis simplement en train de transformer les données existantes d'une certaine manière (mais je veux m'assurer que les données d'origine sont inchangées. 

J'aime utiliser forEach lorsque je modifie la collection en place.

Par exemple,

var b = [{ val: 1 }, { val: 2 }, { val: 3 }];
var c = b.map(function(el) {
    return { val: el.val + 1 }; // modify element in-place
});
console.log(b);
//  [{ val: 1 }, { val: 2 }, { val: 3 }]
console.log(c);
//  [{ val: 3 }, { val: 4 }, { val: 5 }]

Ma règle empirique est de m'assurer que, lorsque vous map, vous créez toujours un nouvel objet/une nouvelle valeur à renvoyer pour chaque élément de la liste source et un renvoi il plutôt qu'une opération sur chaque élément. 

Sauf si vous avez réellement besoin de modifier la liste existante, il n’a pas de sens de la modifier à la place et elle s’intègre mieux dans les styles de programmation fonctionnels/immuables.

1
maschwenk

Encore une fois, je me sens comme un nécromancien ajoutant une réponse à une question qui a été posée il y a 5 ans (heureusement, il y a une activité assez récente, je ne suis donc pas le seul à déranger les morts :).

D'autres ont déjà posté sur votre question principale concernant la différence entre les fonctions. Mais pour...

existe-t-il une utilisation réelle de ces méthodes en javascript (puisque nous ne mettons pas à jour une base de données) autrement que pour manipuler des nombres comme celui-ci:

... c'est drôle tu devrais demander. Aujourd’hui, j’ai écrit un morceau de code qui assigne un certain nombre de valeurs d’une expression régulière à plusieurs variables à l’aide de mappage pour transformation. Il a été utilisé pour convertir une structure textuelle très complexe en données visualisables ... mais pour simplifier, je vais vous donner un exemple en utilisant des chaînes de date, car elles sont probablement plus familières pour tout le monde , au lieu de map, j'aurais utilisé Date-object, qui aurait fait le travail à merveille tout seul).

const DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z$/;
const TEST_STRING = '2016-01-04T03:20:00.000Z';

var [
    iYear,
    iMonth,
    iDay,
    iHour,
    iMinute,
    iSecond,
    iMillisecond
    ] = DATE_REGEXP
        // We take our regular expression and...
        .exec(TEST_STRING)
        // ...execute it against our string (resulting in an array of matches)...
        .slice(1)
        // ...drop the 0th element from those (which is the "full string match")...
        .map(value => parseInt(value, 10));
        // ...and map the rest of the values to integers...

// ...which we now have as individual variables at our perusal
console.debug('RESULT =>', iYear, iMonth, iDay, iHour, iMinute, iSecond, iMillisecond);

Donc… bien que ce ne soit qu'un exemple - et qu’il n’ait procédé qu’à une transformation très élémentaire des données (juste à titre d’exemple)… le fait de faire cela sans carte aurait été une tâche beaucoup plus fastidieuse.

Certes, il est écrit dans une version de JavaScript que je ne pense pas que beaucoup de navigateurs prennent en charge pour le moment (au moins complètement) mais - nous y arrivons. Si je devais l'exécuter dans le navigateur, je crois que cela transpilerait bien.

0
Markku Uttula

TL; DR réponse -

la carte retourne toujours un autre tableau.

car chacun ne le fait pas. C'est à vous de décider ce que ça va faire. Retourne un tableau si vous voulez ou faites autre chose si vous ne le faites pas.

La flexibilité est souhaitable dans certaines situations. Si ce n'est pas pour ce que vous avez à faire, utilisez map.

0
charsi