Why is extending native objects a bad practice?

  1. Home
  2. javascript
  3. Why is extending native objects a bad practice?

Every JS opinion leader says that extending the native objects is a bad practice. But why? Do we get a perfomance hit? Do they fear that somebody does it “the wrong way”, and adds enumerable types to Object, practically destroying all loops on any object?

Take TJ Holowaychuk‘s should.js for example. He adds a simple getter to Object and everything works fine (source).

Object.defineProperty(Object.prototype, 'should', {
  set: function(){},
  get: function(){
    return new Assertion(Object(this).valueOf());
  configurable: true

This really makes sense. For instance one could extend Array.

Array.defineProperty(Array.prototype, "remove", {
  set: function(){},
  get: function(){
    return removeArrayElement.bind(this);
var arr = [0, 1, 2, 3, 4];

Are there any arguments against extending native types?

First answer

When you extend an object, you change its behaviour.

Changing the behaviour of an object that will only be used by your own code is fine. But when you change the behaviour of something that is also used by other code there is a risk you will break that other code.

When it comes adding methods to the object and array classes in javascript, the risk of breaking something is very high, due to how javascript works. Long years of experience have taught me that this kind of stuff causes all kinds of terrible bugs in javascript.

If you need custom behaviour, it is far better to define your own class (perhaps a subclass) instead of changing a native one. That way you will not break anything at all.

The ability to change how a class works without subclassing it is an important feature of any good programming language, but it is one that must be used rarely and with caution.

Second answer

In my opinion, it’s a bad practice. The major reason is integration. Quoting should.js docs:

OMG IT EXTENDS OBJECT???!?!@ Yes, yes it does, with a single getter
should, and no it won’t break your code

Well, how can the author know? What if my mocking framework does the same? What if my promises lib does the same?

If you’re doing it in your own project then it’s fine. But for a library, then it’s a bad design. Underscore.js is an example of the thing done the right way:

var arr = [];
// or: _.flatten(arr)
// NOT: arr.flatten()

Third answer

If you look at it on a case by case basis, perhaps some implementations are acceptable.

String.prototype.slice = function slice( me ){
  return me;
}; // Definite risk.

Overwriting already created methods creates more issues than it solves, which is why it is commonly stated, in many programming languages, to avoid this practice. How are Devs to know the function has been changed?

String.prototype.capitalize = function capitalize(){
  return this.charAt(0).toUpperCase() + this.slice(1);
}; // A little less risk.

In this case we are not overwriting any known core JS method, but we are extending String. One argument in this post mentioned how is the new dev to know whether this method is part of the core JS, or where to find the docs? What would happen if the core JS String object were to get a method named capitalize?

What if instead of adding names that may collide with other libraries, you used a company/app specific modifier that all the devs could understand?

String.prototype.weCapitalize = function weCapitalize(){
  return this.charAt(0).toUpperCase() + this.slice(1);
}; // marginal risk.

var myString = "hello to you.";
// => Hello to you.

If you continued to extend other objects, all devs would encounter them in the wild with (in this case) we, which would notify them that it was a company/app specific extension.

This does not eliminate name collisions, but does reduce the possibility. If you determine that extending core JS objects is for you and/or your team, perhaps this is for you.

Spread the love

Related articles

Comments are closed.