views:

206

answers:

6

I understand from this post, that it's an anti-pattern to modify Object's prototype in JavaScript. I was curious, however, if it's widely considered to be an antipattern to modify other 'built-in' prototypes.

For example: say we wanted to add a setPixel(x,y,color) function to CanvasRenderingContext2D - to abstract out the duty of getting the context's image data, setting a pixel to a certain color, and putting the image data back.

CanvasRenderingContext2D.prototype.setPixel = function(x, y, color){
    var imgdata = this.createImageData(1,1);
    imgdata.data[0] = color.r;
    imgdata.data[1] = color.g;
    imgdata.data[2] = color.b;
    imgdata.data[3] = color.a;
    this.putImageData(imgdata,x,y);
};

I haven't tested this code, but you get the idea. Is something like this against 'best practices' ?

A: 

I don't see any problem with that as long as the functionality or naming does not override what is already there. I know of some that modify the string prototype for Trim functions.

http://www.somacon.com/p355.php

What is funny, C# now has what's called an Extension Method which effectively does the same thing.

Daniel A. White
+4  A: 

I wouldn't do it as it makes it hard to track what is implemented where. It also introduces the risk of two people overriding the same behavior.

Frank Schwieterman
But it can help simplify if one browser has certain functions in their version of Canvas, and you want to add that to another that doesn't include it.
James Black
I agree it makes it hard to track where things are implemented, but it seems like a much more elegant solution than wrapping an object with a custom one just to add one or two functions. So I guess a new question would be: is this "elegance" a fallacy? Kind of like goto statements?
JasonWyatt
I don't think its a fair comparison to goto statements, but I do feel that elegance is a falacy. It may make code look nicer, but for a developer not familiar with the code I think it makes the code harder to understand.
Frank Schwieterman
A: 

Definitely not; if the method is related to the object in this way then it is an elegant solution.

zac
+3  A: 

Generally, if you are adding a prototype to one of the base objects in JavaScript, you should have a good reason, and there is really no reason to modify Object, since you don't know how to predict what the end result will be of that modification.

I tend to add startsWith, trim and some other functions to String, for example, as these are helper functions, just as adding some functions to Array that exists for Firefox but not IE just makes sense (such as the filter function).

So, adding to the Canvas is fine, but, what if someone is using your library, and using excanvas. Will it cause a problem?

You either may want to explore that, or document that it doesn't work for excanvas, and if you have a small test to show that, please include it, so that if later there is a new version, and your problem disappears people can verify that.

UPDATE: You will want to do this:

if (!CanvasRenderingContext2D.setPixel) {
...
}

That way, if someone did include one by that name you will not overwrite it, but you will need to handle it gracefully.

James Black
A: 

Not as itself, but the Ajax library makers might have problems if they cannot rely on the builtin types and their properties. So you could break code that relies on certain behaviour.

Kimmo Puputti
A: 

All of these "anti-pattern" suggestions are not to be blindly adopted. No matter what they say, sometimes the best answer is to bite the bullet and go against convention to get things working. This, of course, largely depends on your scenario.

I'm reminded of a situation where days were spent re-organizing code to make the appropriate fix "the right way", when a simple GO TO would have worked great and only taken a couple of minutes to implement. In the end, a bunch of bugs were created because code was changed that did not need to be changed. Am I a fan of GO TO statements? Hell no! But if using one prevents a months worth of headaches, then there is no question.

Josh Stodola