I am trying to add functionality (new methods) to a built-in object (in my case, of type CanvasRenderingContext2D).
The first approach was to add the methods to the prototype, it works, but I would prefer not to modify built-in objects.
I was thinking to use Object.create (from ES5) to extend the object, something like Object.create(context, <my_method_descriptors>)
, however it fails on some browsers when acessing properties/invoking methods on the extended object. For example, this snippet
var canvas = document.getElementById("mainCanvas");
var context = canvas.getContext('2d');
var exContext = Object.create(context);
try {
exContext.fillStyle = 'red';
exContext.fillRect(0, 0, 120, 120);
} catch (e) {
alert(e);
}
will fail on IE9 Beta and Safari 5 but succeeds on Firefox 4 Beta and Chrome 7.
Another example: Object.create(new Date()).getDate()
fails in all browsers.
Any thoughts?
The CanvasRenderingContext2D
object is a host object, meaning an object that's not part of the JavaScript language but rather an object provided by the environment. There are special rules for host objects: they can essentially do whatever they like and are not obliged to behave in any way like native JavaScript objects. Most browsers make their host objects behave by and large similarly to native objects; IE generally does not (see this recent question for an example piece of IE host object quirkiness).
The consequence of this is that you shouldn't ever rely on host objects to behave like native objects. They're not obliged to and often don't, as in this case. I'd advise creating a wrapper object.
The Object.create(new Date()).getDate()
case is different: the problem there is that the implementation of the getDate()
method relies on the internal time property of the object it's called on, which it cannot access because that particular property is not inherited along the prototype chain. See this discussion for a more detailed explanation.