简体   繁体   中英

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 require 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 iSlice as a method on the Array 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.

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

Which I think is nicer then Alt 1 .

Question

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 Array or String ?

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: ie, 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 = {
    iArray
}

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 (eg 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]) ).

In small doses I think it's not that big of a deal to use Alt 2, but I believe that over usage can create problems. If I remember correctly, they had to completely redo Cut The Rope due to performance problems that I believe stemmed largely in part from prototype extensions. You may also want to consider posting this on https://codereview.stackexchange.com/

A couple references:

http://perfectionkills.com/whats-wrong-with-extending-the-dom/

https://softwareengineering.stackexchange.com/questions/104320/why-is-extending-the-dom-built-in-object-prototypes-a-bad-idea

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM