0

I want to make some functions available to all my arrays.

For instance, I want a function to remove duplicates:

Array.prototype.uniq = function () {
  return Array.from(new Set(this));
};

But I want to make this function work in my entire node.js project.

Will it work if I just put it in server.js which is run when I type npm start?

It would be great if it also works on the client. Is it possible or should I consider server and client strictly separated from one another?

Is it bad practice to extend Array.prototype like this? I just think it seems stupid to write the code many times.

Another options could be to use

function uniquify(arr) {
  return Array.from(new Set(arr));
}

but array.uniq() seems better than uniquify(array).

Jamgreen
  • 10,329
  • 29
  • 113
  • 224

4 Answers4

6

First: If you're going to add properties to Array.prototype, don't add them via simple assignment. Doing so creates enumerable properties, and code that relies on arrays not having any enumerable properties by default will break.

So use defineProperty instead:

Object.defineProperty(Array.prototype, "uniq", {
    value: function uniq() {
      return Array.from(new Set(this));
    }
});

To your questions:

Will it work if I just put it in server.js which is run when I type npm start?

I'm not sure what server.js you're talking about, but if you're talking about modifying files that are built-in parts of Node or npm rather than parts of your project, I strongly recommend not doing so.

It would be great if it also works on the client. Is it possible or should I consider server and client strictly separated from one another?

They're completely separate. If you want to do this on the client, you'll need to include script adding uniq on the client.

Is it bad practice to extend Array.prototype like this? I just think it seems stupid to write the code many times.

There are two camps of thought on that:

  1. Yes, it's bad. You're likely to run into naming conflicts with someone else adding their own, different uniq. Combining code from multiple sources is getting very, very common, increasing the odds of those problems. Future versions of the language may add uniq. Since the committee steering the language (TC-39) tries to steer around potential conflicts, if your client-side library became popular, it would make their work harder. (MooTools has, more than once.)

  2. No, it's not bad, it's what prototypes are for. Naming conflicts can be handled if and when. TC-39 can lump it.

You'll have to make your own decision about whether to do it.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    + for this cool answer. For instance if you add something to the `Object.prototype` like `Object.prototype.compare = func...` it will break jQuery and makes you pull your hair :) yet... this shouldn't avoid you modifying the default properties. Just do it as suggested in this answer. – Redu Sep 19 '16 at 21:35
1

Another option is to extend the array class so that you can get the best of both worlds...

You can add whatever methods you want to your extended newArray class while not polluting the global namespace.

As far as in the browser -- you'll have to do the same thing, though it depends on if you are transpiling ES6 to ES5, limiting yourself to ES6 browsers or if you are looking for a way to make things work in ES5 as well.

Using a factory function to return your newArray type would be one approach -- being mindful to make sure that whatever methods you add are not iterable.

There is a discussion of it here:

Extending Array with ES6 classes

Community
  • 1
  • 1
Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74
  • Good idea. But you don't really need classes for this. [Array sub-classing](https://www.quora.com/What-is-the-array-inheritance-problem-and-why-is-it-so-hard-to-solve/answer/%C3%96mer-Ka%C5%9Fdarma?srid=01By) can still be done with ES6 or even by ES5 by utilizing `Object.setPrototypeOf` or `__proto__` – Redu Sep 19 '16 at 21:43
0

It is considered "bad practice" to manipulate the array prototype.

I (personally) do not think it is so bad to do it with something that has a very "unique" name, but then unique names are hard to come by.

It is much better to have some utility functions that you can call and use when you want to.

Naftali
  • 144,921
  • 39
  • 244
  • 303
  • 1
    It can't just be called "bad practice" without reasoning. Particularly if this is her/his own program, it makes sense that she/he models a domain that suits her/his needs. If the code in question is being designed to distribute to others to include in their own projects, then yes, I'd say it's inconsiderate (ie "bad") to manipulate native prototypes. See @TJCrowder's answer for more apt reasoning. – Mulan Sep 19 '16 at 18:00
  • It's like the "eval is evil" all over again. Sure, if you don't understand `eval`, you're likely to misuse it and welcome heaps of problems. But that doesn't mean its use is not warranted in some distinct scenarios. – Mulan Sep 19 '16 at 18:03
  • Mine and TJs answers are basically the same thing just the other answer has more words. ;-) – Naftali Sep 19 '16 at 18:04
0

For such kind of methods that you want to use multiple times in your application you can create a file like:

appUtils.js

var appUtils = {};

appUtils.getUniqueArray = function () {
  return Array.from(new Set(this));
};

// can add other methods as well

and you can require this file wherever you want to use this function. If you have other reusable methods then can add them as well like above.

Sachin
  • 2,912
  • 16
  • 25