Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The dangers of overwriting JavaScript object and functions

The nature of JavaScript allows for its native objects to be completely re-written. I want to know if there is any real danger in doing so!

Here are some examples of native JavaScript objects

Object
Function
Number
String
Boolean
Math
RegExp
Array

Lets assume that I want to model these to follow a similar pattern that you might find in Java (and some other OOP languages), so that Object defines a set of basic functions, and each other object inherits it (this would have to be explicitly defined by the user, unlike Java, where everything naturally derives from object)

Example:

Object = null;
function Object() {
   Object.prototype.equals = function(other) {
      return this === other;
   }

   Object.prototype.toString = function() {
      return "Object";
   }

   Object.equals = function(objA, objB) {
      return objA === objB;
   }
}

Boolean = null;
function Boolean() {
}
extend(Boolean, Object);  // Assume extend is an inheritance mechanism

Foo = null;
function Foo() {
   Foo.prototype.bar = function() {
      return "Foo.bar";
   }
}

extend(Foo, Object);

In this scenario, Object and Boolean now have new implementations. In this respect, what is likely to happen? Am I likely to break things further down the line?

Edit:

I read somewhere that frameworks such as MooTools and Prototype have a similar approach to this, is this correct?

like image 293
Matthew Layton Avatar asked Jan 08 '13 17:01

Matthew Layton


People also ask

What is prototypal inheritance JavaScript?

The Prototypal Inheritance is a feature in javascript used to add methods and properties in objects. It is a method by which an object can inherit the properties and methods of another object. Traditionally, in order to get and set the [[Prototype]] of an object, we use Object. getPrototypeOf and Object.

What is prototype chaining in JavaScript?

That means all the objects in JavaScript, inherit the properties and methods from Object. prototype. This is called Prototype chaining. This is a very powerful and potentially dangerous mechanism to override or extend object behavior. Objects created using new keyword, inherit from a prototype called Object.

Is JavaScript object based or object oriented?

JavaScript is prototype-based hence it is object-based.


2 Answers

Monkey patching builtin classes like that is a controversial topic. I personally don't like doing that for 2 reaons:

  1. Builtin classes are a global scope. This means that if two different modules try to add methods with the same name to the global classes then they will conflict, leading to subtle bugs. Even more subtly, if a future version of a browsers decides to implement a method with the same name you are also in trouble.

  2. Adding things to the prototypes of common classes can break code that uses for-in loops without a hasOwnProperty check (people new to JS often do that to objects and arrays, since for-in kind of looks like a foreach loop). If you aren't 100% sure that the code you use is using for-in loops safely then monkeypatching Object.prototype could lead to problems.

That said, there is one situation where I find monkeypatching builtins acceptable and that is adding features from new browsers on older browsers (like, for example, the forEach method for arrays). In this case you avoid conflicts with future browser versions and aren't likely to catch anyone by surprise. But even then, I would still recommend using a shim from a third party instead of coding it on your own, since there are often many tricky corner cases that are hard to get right.

like image 78
hugomg Avatar answered Oct 21 '22 05:10

hugomg


There's some level of preference here, but my personal take is that this sort of thing has the potential to become a giant intractable mess.

For example, you start with two projects, A and B, that each decide to implement all sorts of awesome useful fluent methods on String.

Project A has decided that String needs an isEmpty function that returns true if a string is zero-length or is only whitespace.

Project B has decided that String needs an isEmpty function that returns true if a string is zero-length, and an isEmptyOrWhitespace function that returns true if a string is zero-length or is only whitespace.

Now you have a project that wants to use some code from Project A and some code from Project B. Both of them make extensive use of their custom isEmpty functions. Do you have any chance of successfully joining the two? Probably not. You are in a cluster arrangement, so to speak.

Note that this is all very different than extension methods in C#, where you at least have to import the containing static class's namespace to get the extension method, there's no runtime conflict, and could reasonably consume from A and B in the same project as long as you didn't import their extensions namespace (hoping that they had the foresight to put their extension classes in a separate namespace for exactly this reason).

like image 22
Ryan Cavanaugh Avatar answered Oct 21 '22 05:10

Ryan Cavanaugh