Se comprendo correttamente il tuo punto, sembra che tu stia usando male o abusando di every
e some
, ma è un po 'inevitabile se vuoi modificare direttamente gli elementi degli array. Correggimi se ho torto, ma quello che stai cercando di fare è scoprire se alcuni o tutti gli elementi della sequenza mostrano una certa condizione, quindi modificare quegli elementi. Inoltre, il tuo codice sembra applicare qualcosa a tutti gli elementi finché non ne trovi uno che non trasmette il predicato e non penso che sia ciò che intendi fare. In ogni modo.
Prendiamo il tuo primo esempio (leggermente modificato)
if (input.every(function (that) {
return typeof that === "number";
})) {
input.every(function (that) {
that.foo();
}
} else {
return;
}
Quello che stai facendo qui in realtà va un po 'contro lo spirito dei concetti some / every / map / reduce / filter / etc. Every
non è pensato per essere usato per influenzare ogni elemento che è conforme a qualcosa, piuttosto dovrebbe essere usato solo per dirti se ogni oggetto in una collezione lo fa. Se si desidera applicare una funzione a tutti gli elementi per i quali un predicato viene valutato come true, il "buon" modo per farlo è
var filtered = array.filter(function(item) {
return typeof item === "number";
});
var mapped = filtered.map(function(item) {
return item.foo(); //provided foo() has no side effects and returns a new object of item's type instead. See note about foreach below.
});
In alternativa, potresti utilizzare foreach
anziché map per modificare gli elementi sul posto.
La stessa logica si applica a some
, in pratica:
- Si utilizza
every
per verificare se tutti gli elementi in un array superano un test.
- Si utilizza
some
per verificare se almeno un elemento in un array ne supera alcuni
test.
- Si utilizza
map
per restituire un nuovo array contenente 1 elemento (che
è il risultato di una funzione di tua scelta) per ogni elemento in un
matrice di input.
- Si utilizza
filter
per restituire una matrice di lunghezza 0 < length
< initial array length
elementi, tutti contenuti nell'array originale e tutti
superando il test del predicato fornito.
- Si utilizza
foreach
se si desidera una mappa ma sul posto
- Si utilizza
reduce
se si desidera combinare i risultati di una matrice in un risultato a oggetto singolo (che potrebbe essere una matrice ma non deve).
Più le usi (e più scrivi il codice LISP), più ti rendi conto di come sono correlate e di come è possibile emularle / implementarle una con le altre. Ciò che è potente con queste query e ciò che è davvero interessante è la loro semantica, e come ti spingono davvero ad eliminare gli effetti collaterali dannosi nel tuo codice.
EDIT (alla luce dei commenti):
Quindi supponiamo di voler convalidare che ogni elemento è un oggetto e convertirli in un modello di applicazione se sono tutti validi. Un modo per farlo in un singolo passaggio sarebbe:
var dirty = false;
var app_domain_objects = input.map(function(item) {
if(validate(item)) {
return new Model(item);
} else {
dirty = true; //dirty is captured by the function passed to map, but you know that :)
}
});
if(dirty) {
//your validation test failed, do w/e you need to
} else {
//You can use app_domain_objects
}
In questo modo, quando un oggetto non supera la convalida, continui a continuare l'iterazione attraverso l'intero array, che sarebbe più lento della semplice convalida con every
. Tuttavia, la maggior parte delle volte il tuo array sarà valido (o dovrei sperarlo), quindi nella maggior parte dei casi eseguirai un singolo passaggio sull'array e finirai con un array utilizzabile di oggetti del modello di applicazione. La semantica sarà rispettata, gli effetti collaterali evitati e tutti saranno felici!
Si noti che è anche possibile scrivere la propria query, simile a foreach, che applicherà una funzione a tutti i membri di un array e restituirà true / false se tutti superano un test di predicato. Qualcosa come:
function apply_to_every(arr, predicate, func) {
var passed = true;
for(var i = 0; i < array.length; ++i) {
if(predicate(arr[i])) {
func(arr[i]);
} else {
passed = false;
break;
}
}
return passed;
}
Anche se ciò dovrebbe modificare la matrice sul posto.
Spero che questo aiuti, è stato molto divertente scrivere. Cheers!