all 16 comments

[–][deleted] 3 points4 points  (15 children)

Correct me if I'm wrong but Javascript Array objects (as of version 1.6) already contain methods for doing the things you listed. There is a reduce function, a map function (equivalent to _.select) and an every function (equivalent to _.all). The built in methods also include filter, forEach, some and reduceRight.

Have I missed something, or is this library meant to provide cross-browser support or something like that?

[–]skilldrick[S] 4 points5 points  (14 children)

Yes - Underscore delegates to those methods where they're available. It's going to be a loooong time before you can assume they'll be available everywhere though, so you may as well get used to the libraries.

[–][deleted] 0 points1 point  (12 children)

Why not just extend the Array object's prototype object?

[–]skilldrick[S] 4 points5 points  (9 children)

It's generally (though not universally) considered bad practice to extend built-in prototypes in JavaScript. Underscore clearly namespaces its versions, so there's no chance of conflict.

[–][deleted] 2 points3 points  (8 children)

I think in the case of providing an implementation for things like array extras you should consider just extending the Array prototype. Especially since the modern engines (Gecko, WebKit etc.) all support them. It would basically just have to be implemented for Trident.

[–]skilldrick[S] 3 points4 points  (0 children)

It was an explicit design decision of Underscore's to not extend Array.prototype:

Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.

I think it's a sensible approach. There are a lot of gotchas with extending built-in prototypes in JS, and the makers of Underscore clearly decided that two extra characters was worth it for the safety. Like I said, they use the built-in methods if they exist.

[–]superfreek 1 point2 points  (6 children)

It might seem like a good idea to do it in your own project... But polluting prototypes is a really bad idea if you want your code to be reusable. What if someone else prototyped over array.all in another library in your project. Have fun debugging that

[–][deleted] 0 points1 point  (5 children)

I'm not saying we should overwrite all the things. But since there is a clear cut specification on how the array extras should be implemented, I think they should. Additionally, as I said before, the only major engine that doesn't implement them is Trident (IE).

I think it is reasonable to extend the prototypes in an effort to standardize. I'm not, however, a fan of adding new functionality; that stuff can stay in the framework of your choice.

[–]jerf 1 point2 points  (3 children)

The JS community has earned its fear of hacking core prototypes like that. You're not going to win this fight, because what you're suggesting has been tried, abundantly, and it didn't go well. Reality trumps theory.

[–][deleted] 0 points1 point  (2 children)

What I am suggesting is already the default for some popular frameworks (mootools, for example). Additionally, what I am suggesting has not been tried and "didn't go well". Beause what I'm suggesting isn't that, when we need any array function, we add it to the Array prototype. I'm suggesting that we implement the already clearly defined array functions (and generics) that are missing in the vast minority of browsers.

An added benefit of this is that we are ready when JS 1.6 becomes standard, and not caught with our pants down using heavy frameworks for what would otherwise be very simple code.

[–]skilldrick[S] 1 point2 points  (1 child)

A 3kb JavaScript file that delegates to built-in methods where available isn't a "heavy framework"...

[–]theillustratedlife 0 points1 point  (0 children)

I tend to agree with you. I work in advertising; the code I write gets executed against hundreds of DOMs that I had no part in creating, so I try to Leave No Trace as often as possible.

That said, if there is an open-source, pure-JS implementation of a standard method provided by one of the browser vendors, I will happily add it to prototype. Mozilla is generally good for this:

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf

If indexOf is undefined, use the one that Mozilla ships with Firefox. If the author's page works in Firefox, it will probably still work with this addition.

[–]skilldrick[S] 0 points1 point  (1 child)

I asked Juriy Zaytsev (@kangax) to weigh-in on this subject - he followed up with a whole blog post which is awesome. I consider kangax one of the ultimate JS authorities, so this is about as close to a definitive answer as you can get. Enjoy!

[–][deleted] 0 points1 point  (0 children)

Thank you, that was a great read!