Pracuję nad ponownym zapisaniem kodu źródłowego dla wielu standardowych funkcji Underscore.js do pracuję nad moimi umiejętnościami JavaScript i trochę utknąłem z _.every
/_.all
. Wygląda na to, że w samej bibliotece funkcja jest zapisywana tylko przy użyciu istniejącej funkcji _.each
, ale jestem zachęcany do napisania wersji przy użyciu mojej wersji _.reduce
(która już zawiera moją wersję _.each
). Podałem kod dla obu funkcji poniżej.Jak ponownie napisać _.every/_. All z Underscore.js za pomocą _.reduce (i _.each)
Pierwszy test moja _.every
funkcji (patrz poniżej, jak również) nie jest taki, w którym wszystkie fałszywe wartości są przekazywane w użyciu funkcji _.identity
(po prostu zwrócić wartość wprowadzoną jako argument) jako iterator:
Test:
it('fails for a collection of all-falsy results', function() {
expect(_.every([null, 0, undefined], _.identity)).to.equal(false);
});
mam kilka pytań, dlaczego mój _.every
funkcja zawodzi pokazano powyżej testy, wraz z wieloma innymi badaniami (eg; zmieszanych prawda/fałsz, wartości nieokreślonych wartości, etc.):
-Gdy wywołujesz funkcję iteratora, czy muszę używać iterator.call
lub iterator.apply
? Jeśli tak, to jakich użyć i jak określić argumenty?
-Jakie korzyści polega na tym, że zamiast korzystać z _.reduce
zamiast _.each
, szczególnie, gdy biblioteka Underscore.js nie używa _.reduce
?
-Dlaczego nie potrzebuje powrotu na miano dwukrotnie, raz przy wywołaniu funkcji _.reduce
, a raz wewnątrz funkcji anonimowej określonym terminie _.reduce
(Zastanawiałem się to również podczas budowania funkcji, które wykorzystują funkcję _.map
)? Dla mnie wygląda na to, że zwracam wynik funkcji _.reduce
, która już zwraca coś.
_.every:
_.every = function(collection, iterator) {
// TIP: Try re-using reduce() here.
return _.reduce(collection, function(allFound, item) {
return iterator(item) && allFound;
}, true);
};
_.each:
_.each = function(collection, iterator) {
// define spec for arrays
if (Array.isArray(collection)) {
for(var i = 0; i < collection.length; i++) {
iterator(collection[i], i, collection);
}
}
// define spec for objects
else {
for(var key in collection) {
iterator(collection[key], key, collection);
}
}
};
_.reduce:
_.reduce = function(collection, iterator, accumulator) {
// add condition to set accumulator if no explicit starting value is given.
if (arguments.length < 3) {
accumulator = collection[0];
}
_.each(collection, function(value) {
accumulator = iterator(accumulator, value);
});
return accumulator;
};