Over a million developers have joined DZone.

A Java Developer's Perspective on the Power and Danger of JavaScript's Object Prototype

· Web Dev Zone

Start coding today to experience the powerful engine that drives data application’s development, brought to you in partnership with Qlik.

In the Anti-Patterns section of the book Learning JavaScript Design Patterns, author Addy Osmani calls "Modifying the Object class prototype" a "particularly bad anti-pattern." One of the interesting (and scary) aspects of this is that a developer can change the behavior for all JavaScript objects with one definition. This is analogous to what would be possible in Java if a Java developer was allowed to change Java's Object class.

I mentioned this risky feature briefly in my post JavaScript Objects from a Java Developer Perspective. Imagine the havoc that could be rendered if one was able to change, for example, how Java's Object's default equals(Object) implementation was implemented. In the blog post I just mentioned, I demonstrated overriding a particular Java object's toString() implementation. I mentioned, but did not demonstrate, overriding toString() for all JavaScript objects via Object.prototype. In this post, I do demonstrate this, which is the equivalent of what a Java developer could do in Java if allowed to change Java's Object'stoString() implementation directly (Java developers can only extend Object and override it on per-class basis).

It's all too easy to change the default behavior of all JavaScript objects. The next code listing shows how easy it is to change the default JavaScript toString() behavior from providing the string "[object Object]" to providing the string "I'm a JavaScript object!"

Overriding All JavaScript Objects' Default toString() Implementations

Object.prototype.toString = function objectToString()
{
   return "I'm a JavaScript object!";
}

The simple four lines in the above code listing (and I could have easily had them all on a single line) change the default behavior of toString() for all JavaScript objects. I can still override this default implementation of toString on a per named object basis (there are no classes in JavaScript as of today). This was demonstrated in my previous post and is reproduced here for convenience:

Overriding toString() Implementation for Person Object Only

function Person(lastName, firstName)
{
   this.firstName = firstName;
   this.lastName = lastName;
}

Person.prototype.toString = function personToString()
{
   return this.firstName + ' ' + this.lastName;
}

The code listing above shows creation of a JavaScript Person object with a constructor function and shows overriding toString() for that newly created Person object. The next code listing demonstrates testing of the toString() implementations in such a way that the overridden default implementation and the customized Person implementations are rendered. The output of running this demonstration code is shown after the code.

Demonstrating Overridden Default toString() and Customized Person toString()

function demonstrateObjectPrototype()
{
   var indy = new Person('Jones', 'Henry');
   console.log("Indiana Jones's real name is " + indy);

   var solo = {};
   solo.lastName = 'Solo';
   solo.firstName = 'Han';
   console.log("Chewbacca's buddy is " + solo);
}

From the output shown above and the code listing before it, we can see that we have changed the defaulttoString() from "[object Object]" to "I'm a JavaScript object!" and that we can still override a particular object's implementation to use its own customized behavior rather than the default behavior.

It is easy to see how this ability to easily manipulate the default behavior for all JavaScript objects can be both alluring and frightening. It wouldn't be a repeated "pattern" (even if it's an anti-pattern) if it didn't have appeal. Java's default Object.toString() implementation that provides the system identity hashcode of the object upon which it's called rarely seems helpful other than for differentiating it from other objects of the same type. It might be tempting at first, if one could easily change Java's Object's toString(), to change this implementation to use recursion to iterate over all of a given object's data members. However, there would also be significant risks and questions:

  • How would one prevent the toString() that used reflection from showing fields' values that should not be shown for security or other reasons?
  • Would class-level (static) data members be shown in addition to instance-level members?
  • Should all objects pay the reflection performance cost, especially when these objects might include collections of other objects that might lead to reflection on deep collections?
  • What would the preferred output format be?

These questions and concerns regarding overriding default Object.toString() behavior in Java are only a subset of the questions and concerns one might have and it could be argued that changing toString()'s default behavior is less risky than changing the default behavior of other Object methods such asequals(Object). One could always override the behavior in Java of changed default Objectimplementations, but it would need to be overridden in every extended class either directly or through its ancestor classes. Developers new to the code base might assume the JDK default Object behaviors and realize a nasty surprise when they find out that the codebase has changed default Object behaviors.

In this post, I have demonstrated how easy it is to override JavaScript's default Object behaviors via use ofObject.prototype and have tried to also show why this should be rarely or never used. I have intentionally approached this from a Java developer's perspective in an effort to articulate more differences in the object models between Java and JavaScript.

Create data driven applications in Qlik’s free and easy to use coding environment, brought to you in partnership with Qlik.

Topics:
html5 ,javascript ,java

Published at DZone with permission of Dustin Marx, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}