plus

Enhanced Array-like Objects support, Array iteration methods for plain Objects and more

npm install plus
1 downloads in the last month

node-plus

node-plus (or just plus) is a toolbox for nodejs that adds a bunch of functionalities to make node programming easier.

plus is dual licensed under the MIT or GPL Version 2 licenses.

plus is heavily tested internally (more than 160 unique assertions in unit tests) but bugs undoubtedly exist! Don't hesitate to report them and make pull requests if you feel like helping.

In a Nutshell

Array Methods Available Where Needed

Ever dreamed you could use arguments.forEach and cringed at the acrobatics involved? plus makes all the standard Array methods available to Array-like objects. It also provides two separate means to mark objects or even entire classes as Array-like.

plus also introduces the flatten methods for Arrays and Array-like objects, a super useful deep forEach/map kind of method.

Furthermore, when it makes sense, plus provides an implementation of Array methods for non-Array-like objects. So you can use forEach, map, filter and more onto plain objects!

Proper Type Determination

Never understood why typeof new String() returns "object"? Fear not, plus's typeOf( new String() ) will return "string" just like jQuery.type() does!

Arguments object are recognized as "arguments", Regular Expression object as "regexp", etc.

New Plain Object Methods

plus adds extend, deepExtend and hiddenExtend for all your objects merging needs. Dealing with objects has never been easier.

With Array-like objects getting so much love, you'll be happy to know you can use isArrayLike() to determine if your object will behave like an Array or not: very useful when a function parameter can be an Array, an Arguments object or any other kind of Array-like object!

Documentation

Installing

Just use npm: npm install plus

Using

As soon as possible in your project just put require( "plus" );.

Since plus will declare the global function typeOf and augment Object and its prototype, it will "propagate" to the rest of your project. Some people may see this as undesirable and, for any other purpose, I would agree, but it's quite unavoidable given the very nature of what plus does.

Brand New Methods & Functions

Object.prototype.extend( obj1, ..., objN )

will add the properties of obj1 to objN onto the current object. In case of properties already present, they will be overwritten by the newest value.

Object.prototype.deepExtend( obj1, ..., objN )

same as extend except that the process is recursive when values of overwritten properties are objects.

Object.prototype.flatten( [ false, ] [ callback ] )

flattens an Array or Array-like object. When called on a non-Array-like object, return the object in an Array:

  • [ [ 1, 2 ], 3, [ [ 4 ], [ 5 ] ] ].flatten() will return [ 1, 2, 3, 4, 5 ]
  • {}.flatten() will return [ {} ]

if callback is given it acts as a data filter, the returned value is used to fill the resulting array. If an exception is thrown, the value is simply skipped and left out of the resulting array. For instance, the following code will return [ 4, 8 ]:

[ [ 1, 2 ], 3, [ [ 4 ], [ 5 ] ] ].flatten(function( value ) {
    if ( value % 2 ) {
        throw "odd";
    }
    return 2 * value;
});

if false is given as first argument, then no array is constructed (flatten will return undefined) but callback will be called nonetheless:

var tmp = 0;
[ [ 1, 2 ], 3 ].flatten(function( value ) {
    tmp += value;
});
console.log( tmp ); // outputs 6

Object.prototype.hiddenExtend( obj1, ..., objN )

same as extend except the added properties won't be iterable using a for..in statement.

Object.prototype.isArrayLike()

returns true if an Object is an Array or an Array-like Object, false otherwise.

typeOf( obj )

returns the type of obj. This is equivalent to the typeof operator for non-Objects but will return the correct type for instantiated values. For instance, typeOf( new String() ) will return "string" not "class".

Array Methods

The following table shows for which type of Object each Array method is implemented:

Method Array-like Objects Objects
concat YES NO
every YES YES
filter YES YES
flatten YES YES
forEach YES YES
indexOf YES YES
join YES YES
lastIndexOf YES YES
map YES YES
pop YES NO
push YES NO
reduce YES YES
reduceRight YES YES
reverse YES YES
shift YES NO
slice YES NO
splice YES NO
some YES YES
sort YES YES
unshift YES NO

For those methods rewritten for Plain Objects, the algorithm is as much of a direct translation as possible with the notable exception of sort which, while sorting according to the value, will keep the key/value correspondances of the object. For instance, { "a": 2, "b": 1 }.sort(); will change the object into { "b": 1, "a": 2 }.

Please note that, because of a BUG (Google devs can argue all they want, three years and more than a hundred comments later, it is still a bug in V8), the engine does not ensure consistent ordering of properties in Objects when one or more keys are numbers (or parsable as numbers, which is even worse). As such, some of the methods will probably not work as you would expect if you use numbers as keys. Let's pray the V8 devs get back to their senses one day. In the meantime, don't use numbers as keys in non-Array-like objects.

Tagging a Class or Object as "Array-like"

The simplest way to tag a Class as Array-like is to add a __array_like__ boolean property set to true to its prototype. We recommand using Object.defineProperty so that the property is not iterable using a for...in statement:

Object.defineProperty( MyConstructor.prototype, "__array_like__", { "value": true } );

If your code is not prototype-based (but rather uses Plain Objects created in closures), you can create the property onto the Object itself:

Object.defineProperty( myPlainObject, "__array_like__", { "value": true } );

If you're using Objects from a third-party library and can't (or don't want to) change the library's code, look up what value typeOf returns for this type of Objects and add an entry on the Object.arrayTypes map:

Object.arrayTypes[ "thetype" ] = true;

plus will take care of the rest from there! ;)

npm loves you