npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

plus

v0.1.0

Published

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

Downloads

867

Readme

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! ;)