Joakim Ericsson Joakim Ericsson - 1 month ago 8x
Node.js Question

Best practice when adding custom method to Array (Built-in object)

I have created a node module with a couple of custom methods for arrays and strings.

First I just used it like a regular module and got the functions from a

like this:

Alt 1.

const invSlice = require('inverted-slice');
let arr1 = [1,2,3,4];
invSlice.iSlice(arr, start, stop);

This works but it would be nicer to call
as a method on the
object. I solved this by adding the following code in my library:

Array.prototype.iSlice = iSliceBuiltin; // iSliceBuiltin is my function

And the method can now be used like:

Alt 2.

let arr1 = [1,2,3,4];
arr1.iSlice(start, stop);

Which I think is nicer then Alt 1.


My question is if there is any best practice or guidelines to follow when adding custom methods like in Alt 2 to built-in Objects like


Extending built-in prototypes has always triggered debates, and I think we can conclude it is not considered best practice.

On the other hand it is indeed nice if you can call these custom methods as object methods instead of plain functions.

You might consider a wrapper function that will return an Array instance that has the extra methods defined for it: i.e., not on the prototype, but on the Array instance itself.

Your module could look like this:

function iArray(arr) {
    return Object.assign([], arr || [], {
        iSlice: iSliceBuiltin,
        iSplice: iSpliceBuiltin

// ... your module functions come here, but excluding the changes to the Array prototype

module.exports = {

Then you would use it like this:

const iArray = require('inverted-slice');

let arr1 = iArray([1,2,3,4]); // enrich array with extra methods
let result = arr1.iSlice(0, 1);

To allow chaining, you could change the return statement in iSliceSpliceHelper to:

return iArray(newArr);

So, now you can write:

let arr1 = iArray([1,2,3,4]); // enrich array with extra methods
let result = arr1.iSlice(0, 1).iSlice(1, 2);

Existing libraries might implement your alternative 1 (e.g. underscore), but many also go for something like I propose here. See for instance Sugar (new Sugar.Array([1,2,3])), or Lazy (Lazy([1,2,3])).