javascript - How to re-write _.every/_.all from Underscore.js using _.reduce (and _.each) -



javascript - How to re-write _.every/_.all from Underscore.js using _.reduce (and _.each) -

i'm working on re-writing underlying code many of standard underscore.js functions work on javascript skills , bit stuck _.every/_.all. appears in library itself, _.every/_.all function written using existing _.each function, beingness encouraged write version using version of _.reduce (which incorporates version of _.each). i've provided code both functions below.

the first test _.every function (see below well) fails 1 false values passed in using _.identity function (simply homecoming value entered argument) iterator:

test:

it('fails collection of all-falsy results', function() { expect(_.every([null, 0, undefined], _.identity)).to.equal(false); });

i have few questions why _.every function failing test shown above, along multiple other tests (e.g.; mixed true/false values, undefined values, etc.):

-when calling iterator function, need utilize iterator.call or iterator.apply? if so, utilize , how specify arguments?

-what benefit there using _.reduce here rather _.each, when underscore.js library not utilize _.reduce?

-why homecoming need called twice, 1 time when calling _.reduce function, , 1 time within anonymous function defined within _.reduce (i've wondered when building functions utilize _.map function)? me, seems returning result of _.reduce function, returning something.

_.every:

_.every = function(collection, iterator) { // tip: seek re-using reduce() here. homecoming _.reduce(collection, function(allfound, item) { homecoming iterator(item) && allfound; }, true); };

_.each:

_.each = function(collection, iterator) { // define spec arrays if (array.isarray(collection)) { for(var = 0; < collection.length; i++) { iterator(collection[i], i, collection); } } // define spec objects else { for(var key in collection) { iterator(collection[key], key, collection); } } };

_.reduce:

_.reduce = function(collection, iterator, accumulator) { // add together status set accumulator if no explicit starting value given. if (arguments.length < 3) { accumulator = collection[0]; } _.each(collection, function(value) { accumulator = iterator(accumulator, value); }); homecoming accumulator; };

your test isn't passing because it's not returning false expected (though returning falsey value).

_.every = function(collection, iterator) { homecoming _.reduce(collection, function(allfound, item) { homecoming iterator(item) && allfound; }, true); };

what happens when homecoming iterator(item) && allfound if iterator(item) falsey (but not false), not homecoming false, value of iterator(item). verify yourself, open repl, , type undefined && true; result undefined, not false.

so if want explicitly homecoming false, , not falsey value, you'll have coerce boolean. can either boolean(truthy_or_falsey_value) or !!truthy_or_falsey_value. prefer latter, alter implementation thusly:

_.every = function(collection, iterator) { homecoming _.reduce(collection, function(allfound, item) { homecoming !!iterator(item) && allfound; }, true); };

your other questions:

when calling iterator function, need utilize iterator.call or iterator.apply? if so, utilize , how specify arguments?

it depends on goal is. call , apply used when want command value of this keyword in function body. of javascript's built-in array methods (like array.prototype.map , array.prototype.filter) take thisarg, supplied callback using call or apply. far difference between call , apply, it's how arguments handled. see this answer more details.

what benefit there using reduce here rather each, when underscore.js library not utilize reduce?

probably none, or little. there performance difference, best way find out profile both approaches.

why homecoming need called twice, 1 time when calling _.reduce function, , 1 time within anonymous function defined within _.reduce

if want function -- function -- homecoming value, must phone call homecoming within function. can't expect phone call return inner function, , expect enclosing function magically understand it's supposed to, in turn, homecoming value of called function. languages default returning value of lastly look in function if return isn't explicitly called, either convenient or confusing, depending on perspective. if have experience such language (ruby, example), return statements may seem little excessive you.

as editorial note, sense iterator poor naming selection testing function. not iterating on (the function it's argument doing iteration). improve name might generic callback or cb. term "predicate" means function maps value true or false, preferred terminology. mutual selection test, since is, after all, function that's performing binary filter on argument.

javascript underscore.js

Comments

Popular posts from this blog

php - Android app custom user registration and login with cookie using facebook sdk -

c# - Create a Notification Object (Email or Page) At Run Time -- Dependency Injection or Factory -

Set Up Of Common Name Of SSL Certificate To Protect Plesk Panel -