node.js utility library for working with objects and arrays? - javascript

Is there good utility library for working with objects and arrays.
For example functions like: extend, forEach, copying objects/arrays ect,
What is common in node.js environments? I wonder are there decent alternatives to underscore.js?

underscore.js is a pretty good default for this kind of stuff. Here's a thread on compatibility issues that may be handy.
Edit, upon you're request for something beyond underscore:
As far as I know, underscore has become the defacto standard when you're looking for additional array operations (much like jQuery for DOM manipulation). Joyent maintains a pretty thorough manifest of node.js compatible modules, and the only seemingly comparable utility would appear to be an experimental library called fjs with an emphasis on currying (and judging from the source, most of the functionality comes from extending underscore functions anyway). There might be something else out there, but as far as I know nothing with the penetration and maturity of underscore.
Yet another edit - here are a handful of older libraries if you're so curious, but their maintenance has fallen off a bit - valentine, wu.js, Functional, and Sugar. Functional and valentine may be a bit thinner; wu.js looks to be about the same and sugar is even fatter.

lodash is a "drop-in replacement* for underscore.js" that you may also want to consider.
Lo-Dash v0.7.0 has been tested in at least Chrome 5-21, Firefox 1-15, IE 6-9, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.8, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5

For extend specifically, you can use Node's built-in util._extend() function.
var
extend = require('util')._extend,
x = {a:1},
y = extend({}, x);
Source code of Node's _extend function: https://github.com/joyent/node/blob/master/lib/util.js#L563

Have a look at Ramdajs: http://ramdajs.com/0.22.1/index.html
The primary distinguishing features of Ramda are:
Ramda emphasizes a purer functional style. Immutability and
side-effect free functions are at the heart of its design philosophy.
This can help you get the job done with simple, elegant code.
Ramda functions are automatically curried. This allows you to easily
build up new functions from old ones simply by not supplying the final
parameters.
The parameters to Ramda functions are arranged to make it convenient
for currying. The data to be operated on is generally supplied last.
The last two points together make it very easy to build functions as
sequences of simpler functions, each of which transforms the data and
passes it along to the next. Ramda is designed to support this style
of coding.

Related

Whether to use [array].filter or _.filter

my project includes underscorejs as a dependency. Internally I need to do a lot of complex array operations which basically includes me mapping over or filtering or reducing an array. We have native map, filter, reduce methods on Array.prototype. But the same methods are also available in underscorejs.
Personally, it makes more sense for me to use the native methods as it feels more natural in place of a wrapped object like _(array).filter(function(){}) or maybe _.filter(array, function(){}).
Please suggest.
This is really an opinion based question. Lodash will give you better browser support and possibly better performance, while the native functions might be arguably more clear on what they are doing. The native functions also handle some edge cases with sparse arrays and such, which may or may not be relevant to you.
Whatever floats your boat.
Personally I'd go for consistency. If you are already using underscore or lodash for their functions that aren't natively implemented (like _.uniq or _.pick) I'd just keep using _.filter and whatnot too.
If you need quite some complex operation go for underscore with the _.chain()
So you can chain call like this :
_.chain(array).filter(function(){}).pluck('name').unique();
This sample will extract all unique name of the matched data in the filter.
Unlike native function, this library has been developped to be more easy to use and provide a good performance without having any problems with browser compatibility.

Why does Underscore.js define function aliases

Underscore.js defines aliases for functions like _.each (alias: forEach) and _.map (alias: collect) and I don't understand why.
I initially thought this was to avoid issues with browsers that didn't implement those functions natively, my thinking was that calling [].map() would throw an error in IE7 and 8 because they didn't implement it natively but found that there was no issue since Underscore already defines those.
Then I thought it could have something to do with conflicts with other JS libraries like Prototype that implement similarly named functions but then realised that having an alias doesn't actually make a difference in the case of _.map since prototype implements .map and .colelct and actually I'd been using prototype's implementation all along (eg. this.collection.collect(...)).
So far it doesn't seem to have made any difference and it hasn't created any issues but I'd really like to know why this is happening.
I guess the purpose of aliases is to make the library more familiar for programmers with different backgrounds (eg, collect and include are used in Ruby, fold in functional languages etc).
Also, aliases can improve readability in some cases, for example
list.select(...).reject(...)
"sounds" better than
list.filter(...).reject(...)
If you look at their documentation, you will find it pretty close to lodash library (http://lodash.com/), and jQuery's library, and also Backbone and Ruby (found in the home page).
My guess, is that both of them are made to do the same thing, one in Server (Lodash), other in Client (Underscore), and to use the same syntax, they have some methods aliases.
Also, adding some aliases is never good, since it decreases errors when writing in multiple languages.

js library to support various data structures? (like guava in java)

Coming from Java I really like the flexibility afforded by the rich collection of data structures provided by Guava. Is there a "guava-like" library in js or jquery?
Note: I heard about closure and it seems a bit heavy - anything simpler? (or is closure really what I need?)
Note 2: by "rich collection of data structures" I mean sorted maps and sets, multimaps (duplicate keys allowed) and multisets (sets with multiple entries allowed - seems strange but actually very useful!), etc.
If by "the rich collection of data structures" for JS you meant utility for operating on JavaScript Arrays and Objects and JavaScript itself, then I'd recommend Underscore.js:
Underscore is a utility-belt library for JavaScript that provides a
lot of the functional programming support. (...) Underscore provides
60-odd functions that support both the usual functional suspects: map,
select, invoke — as well as more specialized helpers: function
binding, javascript templating, deep equality testing, and so on. It
delegates to built-in functions, if present, so modern browsers will
use the native implementations of forEach, map, reduce, filter, every,
some and indexOf.
It also has Set-like functions like union, intersection and difference, type-checking functions isXXX (isArray etc.), function goodies and more stuff you'd write yourself without such a library.
Underscore has clean code, is well tested and quite popular these days, I use it on daily basis in JS projects.
EDIT after question edit:
I know Guava has multimaps, multiset etc. but they are all consequesnce of Java design and it's hard to write 1 to 1 implementation of these collections in JS. It's because Javascript has no:
static typing,
classes in Java sense, uses prototyping instead (see this answer),
interfaces (but has functions as first-class objects on the other hand),
easily defined object equality (var t1 = { test: 1 }, t2 = { test: 1 }; t1 === t2 is false)
so it's hard to write general-use Set implementation, not mentioning Multiset or Multimap. There are for example some Set implementations like Closure's one or this one, but they are not perfect - first modifies elements inserted into Set (!), the second is not a mainstream, well-tested project (and personally I've never used it so can't say more).
In Javascript you just do var multimap = { key: [ 1, 2, 3.0 ], key2: [ 4, 'test', { bla: null }, 1 ] } and because of language design you can't just do multimap.containsValue({ bla: null }). I mentioned underscore.js because it has 95% utility functions you'll ever with JS collections, that is Arrays and Objects. If you want more, just use Closure's structs, but the library itself it's quite big.
There is a now a lighter, faster alternative to Underscore.js: Lo-Dash (http://lodash.com/).
js-sdsl
A javascript standard data structure library which benchmark against C++ STL.
This library has strict time complexity guarantee and can be used with confidence.
The latest beta version includes iterator functions which can be used like iterator in c++.
Included data structures
Vector
Stack
Queue
LinkList
Deque
PriorityQueue
Set (using RBTree)
Map (using RBTree)
HashSet (for reference only)
HashMap (for reference only)
Usage
To help you have a better use, we provide this API document.

Linq for JavaScript vs standard methods

I am an architect for a software development team. I have built a sizeable warchest of web controls and tools for us using ASP.NET and JavaScript/jQuery.
Part of the toolkit is a functional equivalent to .NET's IEnumerable LINQ methods (where, select, etc.) for JavaScript arrays. I was surprised how simple these were to implement using the js prototype feature. My hope was that our devs could leverage their knowledge of LINQ seamlessly on the client side, and the results have been great so far.
There is just one snag, as I discovered today: there are already a handful of functionally identical methods as of JavaScript 1.6. They are filter, map, some, and every, corresponding to LINQ's where, select, any, and all methods, respectively.
They aren't supported by IE8 or earlier (which might explain why I had not heard about them), but it is trivial to provide an implementation so that they work cross-browser. Note that there are dozens of LINQ methods that do not have a native equivalent, such as sum, max, avg, groupBy, etc.
My question is this: how should my development team address this discrepancy? I think we have three options:
1 - Ignore the native JavaScript methods (or consume them internally in a pass through method) and use only the LINQ methods. Forbid the use of the native methods so that our codebase is self-consistent.
2 - Use the native JavaScript methods whenever applicable, and the LINQ methods when there is no equivalent.
3 - Allow either to be used.
I will suppose that most of the community will side with Option 2, as it is arguably more standards-compliant, but I feel it will be disorienting for devs to have to know that some functions are identical in JavaScript, while others have a different, arbitrary name. It really jacks up the cross-platform consistency we have achieved so far.
Which of these would you choose, and why? Is there another alternative I am not considering?
Bonus Question: jQuery has neither native functions nor LINQ functions. What method names should my jQuery extensions use?
I would opt for #1 out of the three you provided, because I value consistency, but also because it allows you to provide a fallback if the method is not natively available.
That's also similar to what Underscore.js does for some of its methods --- uses native implementation if available, otherwise resorts to its fallback implementation.
You can try manipula package that implements all of C# LINQ methods and preserves its syntax:
https://github.com/litichevskiydv/manipula
https://www.npmjs.com/package/manipula

Why is it frowned upon to modify JavaScript object's prototypes?

I've come across a few comments here and there about how it's frowned upon to modify a JavaScript object's prototype? I personally don't see how it could be a problem. For instance extending the Array object to have map and include methods or to create more robust Date methods?
The problem is that prototype can be modified in several places. For example one library will add map method to Array's prototype and your own code will add the same but with another purpose. So one implementation will be broken.
Mostly because of namespace collisions. I know the Prototype framework has had many problems with keeping their names different from the ones included natively.
There are two major methods of providing utilities to people..
Prototyping
Adding a function to an Object's prototype. MooTools and Prototype do this.
Advantages:
Super easy access.
Disadvantages:
Can use a lot of system memory. While modern browsers just fetch an instance of the property from the constructor, some older browsers store a separate instance of each property for each instance of the constructor.
Not necessarily always available.
What I mean by "not available" is this:
Imagine you have a NodeList from document.getElementsByTagName and you want to iterate through them. You can't do..
document.getElementsByTagName('p').map(function () { ... });
..because it's a NodeList, not an Array. The above will give you an error something like: Uncaught TypeError: [object NodeList] doesn't have method 'map'.
I should note that there are very simple ways to convert NodeList's and other Array-like
Objects into real arrays.
Collecting
Creating a brand new global variable and stock piling utilities on it. jQuery and Dojo do this.
Advantages:
Always there.
Low memory usage.
Disadvantages:
Not placed quite as nicely.
Can feel awkward to use at times.
With this method you still couldn't do..
document.getElementsByTagName('p').map(function () { ... });
..but you could do..
jQuery.map(document.getElementsByTagName('p'), function () { ... });
..but as pointed out by Matt, in usual use, you would do the above with..
jQuery('p').map(function () { ... });
Which is better?
Ultimately, it's up to you. If you're OK with the risk of being overwritten/overwriting, then I would highly recommend prototyping. It's the style I prefer and I feel that the risks are worth the results. If you're not as sure about it as me, then collecting is a fine style too. They both have advantages and disadvantages but all and all, they usually produce the same end result.
As bjornd pointed out, monkey-patching is a problem only when there are multiple libraries involved. Therefore its not a good practice to do it if you are writing reusable libraries. However, it still remains the best technique out there to iron out cross-browser compatibility issues when using host objects in javascript.
See this blog post from 2009 (or the Wayback Machine original) for a real incident when prototype.js and json2.js are used together.
There is an excellent article from Nicholas C. Zakas explaining why this practice is not something that should be in the mind of any programmer during a team or customer project (maybe you can do some tweaks for educational purpose, but not for general project use).
Maintainable JavaScript: Don’t modify objects you don’t own:
https://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
In addition to the other answers, an even more permanent problem that can arise from modifying built-in objects is that if the non-standard change gets used on enough sites, future versions of ECMAScript will be unable to define prototype methods using the same name. See here:
This is exactly what happened with Array.prototype.flatten and Array.prototype.contains. In short, the specification was written up for those methods, their proposals got to stage 3, and then browsers started shipping it. But, in both cases, it was found that there were ancient libraries which patched the built-in Array object with their own methods with the same name as the new methods, and had different behavior; as a result, websites broke, the browsers had to back out of their implementations of the new methods, and the specification had to be edited. (The methods were renamed.)
For example, there is currently a proposal for String.prototype.replaceAll. If you ship a library which gets widely used, and that library monkeypatches a custom non-standard method onto String.prototype.replaceAll, the replaceAll name will no longer be usable by the specification-writers; it will have to be changed before browsers can implement it.

Categories

Resources