On m'a toujours appris qu'avoir des effets secondaires dans une if
condition était mauvais. Ce que je veux dire est;
if (conditionThenHandle()) {
// do effectively nothing
}
... par opposition à;
if (condition()) {
handle();
}
... et je comprends cela, et mes collègues sont heureux parce que je ne le fais pas, et nous rentrons tous chez nous à 17h00 un vendredi et tout le monde a un joyeux week-end.
Maintenant, ECMAScript5 a introduit des méthodes comme every()
et some()
à Array
, et je les trouve très utiles. Ils sont plus propres que for (;;;)
les autres, vous donnent une autre portée et rendent l'élément accessible par une variable.
Cependant, lors de la validation de l'entrée, je me retrouve le plus souvent à utiliser every
/ some
dans la condition pour valider l'entrée, puis à utiliser every
/ à some
nouveau dans le corps pour convertir l'entrée en un modèle utilisable;
if (input.every(function (that) {
return typeof that === "number";
})) {
input.every(function (that) {
// Model.findById(that); etc
}
} else {
return;
}
... quand ce que je veux faire, c'est;
if (!input.every(function (that) {
var res = typeof that === "number";
if (res) {
// Model.findById(that); etc.
}
return res;
})) {
return;
}
... ce qui me donne des effets secondaires dans un if
état, ce qui est mauvais.
En comparaison, c'est le code qui ressemblerait à un ancien for (;;;)
;
for (var i=0;i<input.length;i++) {
var curr = input[i];
if (typeof curr === "number") {
return;
}
// Model.findById(curr); etc.
}
Mes questions sont:
- Est-ce définitivement une mauvaise pratique?
- Suis-je (mis | ab) en utilisant
some
etevery
( devrais- je utiliser unfor(;;;)
pour cela?) - Est-ce qu'il y a une meilleure approche?
some
, je veux faire quelque chose avec l'élément, si j'utiliseevery
, je veux faire quelque chose avec tous ces éléments ...some
etevery
ne me laisse pas accéder à cette information, donc soit je ne peux pas les utiliser, ou je dois ajouter des effets secondaires.some
dans monif
état pour déterminer si un certain élément du tableau présente une propriété, 9/10 je dois fonctionner sur cet élément dans monif
corps; maintenant, commesome
ne me dites pas que des éléments exposés la propriété (juste « un fait »), je peux soit utiliser àsome
nouveau dans le corps (O (2n)), ou je peux effectuer l'opération à l' intérieur du si la condition ( ce qui est mauvais, car c'est un effet secondaire dans la tête).every
même, bien sûr.Réponses:
Si je comprends bien votre point, vous semblez mal utiliser ou abuser
every
,some
mais c'est un peu inévitable si vous voulez changer directement les éléments de vos tableaux. Corrigez-moi si je me trompe, mais ce que vous essayez de faire est de savoir si certains ou tous les éléments de votre séquence présentent une certaine condition, puis modifiez ces éléments. De plus, votre code semble appliquer quelque chose à tous les éléments jusqu'à ce que vous en trouviez un qui ne passe pas le prédicat et je ne pense pas que c'est ce que vous voulez faire. Bref.Prenons votre premier exemple (légèrement modifié)
Ce que vous faites ici va en fait un peu à l'encontre de l'esprit des concepts some / every / map / réduire / filtre / etc.
Every
n'est pas censé être utilisé pour affecter chaque élément conforme à quelque chose, mais doit uniquement être utilisé pour vous dire si chaque élément d'une collection le fait. Si vous souhaitez appliquer une fonction à tous les éléments pour lesquels un prédicat est évalué comme vrai, la "bonne" façon de le faire estAlternativement, vous pouvez utiliser
foreach
au lieu de la carte pour modifier les éléments sur place.La même logique s'applique
some
, essentiellement:every
pour tester si tous les éléments d'un tableau réussissent un test.some
pour tester si au moins un élément d'un tableau réussit un test.map
pour renvoyer un nouveau tableau contenant 1 élément (qui est le résultat d'une fonction de votre choix) pour chaque élément d'un tableau d'entrée.filter
pour retourner un tableau de longueur 0 <length
<initial array length
éléments, tous contenus dans le tableau original et tous passer le test sous - jacente fournie.foreach
si vous voulez une carte mais en placereduce
si vous souhaitez combiner les résultats d'un tableau dans un résultat d'objet unique (qui pourrait être un tableau mais pas nécessairement).Plus vous les utilisez (et plus vous écrivez de code LISP), plus vous réalisez comment ils sont liés et comment il est même possible d'émuler / implémenter l'un avec les autres. Ce qui est puissant avec ces requêtes et ce qui est vraiment intéressant, c'est leur sémantique, et comment elles vous poussent vraiment à éliminer les effets secondaires nuisibles dans votre code.
EDIT (à la lumière des commentaires): disons que vous voulez valider que chaque élément est un objet et les convertir en modèle d'application s'ils sont tous valides. Une façon de le faire en un seul passage serait:
De cette façon, lorsqu'un objet ne passe pas la validation, vous continuez à parcourir le tableau entier, ce qui serait plus lent que la simple validation avec
every
. Cependant, la plupart du temps, votre tableau sera valide (ou je l'espère), donc dans la plupart des cas, vous effectuerez un seul passage sur votre tableau et vous vous retrouverez avec un tableau utilisable d'objets de modèle d'application. La sémantique sera respectée, les effets secondaires évités et tout le monde sera content!Notez que vous pouvez également écrire votre propre requête, similaire à foreach, qui appliquerait une fonction à tous les membres d'un tableau et renvoie true / false s'ils passent tous un test de prédicat. Quelque chose comme:
Bien que cela modifierait le tableau en place.
J'espère que cela aide, c'était très amusant à écrire. À votre santé!
la source
if (input.every())
, pour vérifier que chaque élément est un objet (typeof el === "object && el !== null
) etc., puis si cela valide, je veux convertir chaque élément en le modèle d'application respectif (que vous mentionnez maintenant quemap()
je pourrais utiliserinput.map(function (el) { return new Model(el); });
, mais pas nécessairement en place .map()
je dois répéter deux fois le tableau; une fois pour valider et une autre pour convertir. Cependant, en utilisant une norme enfor(;;;)
boucle, je pouvais le faire en utilisant une itération, mais je ne peux pas trouver un moyen d'appliquerevery
,some
,map
oufilter
dans ce scénario, et d' exécuter seulement une passe, sans avoir effets secondaires indésirables ou l' introduction d' ailleurs mauvais- entraine toi.Les effets secondaires ne sont pas dans l'état if, ils sont dans le corps de l'if. Vous avez uniquement déterminé si vous souhaitez ou non exécuter ce corps dans l'état réel. Il n'y a rien de mal à votre approche ici.
la source
if
condition, avec seulement l'return
être à l'intérieur duif
corps de; de toute évidence, je parle de l'exemple de code précédé de " ce que vous voulez faire est; ...if
état.