Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending JavaScript's built-in types - is it evil? [closed]

Tags:

javascript

I've read a few articles that suggest extending the built-in objects in JavaScript is a bad idea. Say for example I add a first function to Array...

Array.prototype.first = function(fn) {
    return this.filter(fn)[0];
};

Great, so now I can get the first element based on a predicate. But what happens when ECMAScript-20xx decides to add first to the spec, and implement it differently? - well, all of a sudden, my code assumes a non-standard implementation, developers lose faith, etc.

So then I decide to create my own type...

var Enumerable = (function () {
    function Enumerable(array) {
        this.array = array;
    }
    Enumerable.prototype.first = function (fn) {
        return this.array.filter(fn)[0];
    };
    return Enumerable;
}());

So now, I can pass an array into a new Enumerable, and call first on the Enumerable instance instead. Great! I've respected the ECMAScript-20xx spec, and I can still do what I want it to do.

Then the ES20XX+1 spec is released which introduces an Enumerable type, which doesn't even have a first method. What happens now?

The crux of this article boils down to this; Just how bad is it to extend the built in types, and how can we avoid implementation collisions in future?

Note: The use of namespaces might be one way to deal with this, but then again, it isn't!

var Collection = {
    Enumerable: function () { ... }
};

What happens when the ECMAScript spec introduces Collection?

like image 585
Matthew Layton Avatar asked Oct 31 '16 13:10

Matthew Layton


People also ask

Can you extend a built-in type?

Built-in classes like Array, Map and others are extendable also. Please note a very interesting thing. Built-in methods like filter , map and others – return new objects of exactly the inherited type PowerArray .

Is it possible to extend built-in classes in JS?

Array, Map, and other built-in classes are extendable. The most impressive thing is that built-in methods such as map , filter, and more - return new objects of literally the inherited type NumsArray .

How do you extend an object?

The extends keyword can be used to extend the objects as well as classes in JavaScript. It is usually used to create a class which is child of another class. Syntax: class childclass extends parentclass {...}

What is extend in JavaScript?

The extends keyword is used to create a child class of another class (parent). The child class inherits all the methods from another class. Inheritance is useful for code reusability: reuse properties and methods of an existing class when you create a new class.


2 Answers

This is precisely the reason why you must try to pollute the global namespace as little as possible. The only way to completely avoid any sort of clashes is by defining everything within an IIFE:

(function () {
    let Collection = ...
})();

If and only if you need to define global objects, for instance because you're a library and you want to be used by 3rd parties, you should define a name which is extremely unlikely to clash, for instance because it's your company name:

new google.maps.Map(...)

Any time you define a global object, which includes new methods on existing types, you're running the risk of some other library or some future ECMAScript standard trying to co-opt the name sometime in the future.

like image 132
deceze Avatar answered Sep 18 '22 17:09

deceze


The issue with the first approach is that you extend the prototype for all scripts on your page.

If you were to include a third-party script which relies on the new, native ES-20xx Array.prototype.first method, then you would break it with your code.

The second example is only really a problem, if you were to use global variables (which I hope you are not doing…). Then the same problem could happen.

The thing is, spec authors are increasingly wary of not destroying the existing web, so they have to rename future features if too many existing sites break. (And this is also why you should not create polyfills for web platform specs which are not yet finalized, BTW)

The issue is certainly bigger if you create a library or a framework that extends native objects and is used by 100s or 1000nds of websites. That's when you start hindering the standards process.

If you use your variables within a function or a block scope, and you don't rely on future features, you should be just fine.

Function scope example:

(function() {
  var Enumerable = {};
})();

Block scope example:

{
    const Enumerable = {};
}
like image 29
nils Avatar answered Sep 18 '22 17:09

nils