2

In jQuery you can call a function like this for example:

$("id").someFunction();

Now after looking at the codebase of jQuery it looks like the object being created by using $ has its protoype modified to return the function which was added via .fn, in my application I would like the same syntax only without requiring jQuery.

Another example of this kind of behavior is some of Javascript's in-built methods such as: .replace, .toLowerCase, .split, .toString, etc. I understand some of those listed methods are on the String.prototype object and extending in-built objects is bad practice (so I hear).

How am I able to add a function to the prototype of every "String" or "Object" that gets assigned. The reason I am doing this is I am trying to create a cross-browser implementation of attaching events without having to do if statements all of the time.

So instead of needing to go: if (el.addEventListener) or if (el.attachEvent) I would like to be able to go el.bindEvent which behind the scenes would be a prototype method behind the scenes that would do all of the checking for event binding, etc.

My advanced JS knowledge when it comes to assigning prototype methods and whatnot isn't that great, so your help in understanding and correcting anything I've said is appreciated.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Dwayne Charrington
  • 6,524
  • 7
  • 41
  • 63
  • Extending the prototype of DOM elements is an even worse idea than extending built-in objects. Have a look at http://perfectionkills.com/whats-wrong-with-extending-the-dom/. *"cross-browser implementation of attaching events without having to do if statements all of the time"*: All you have to to is create one function `function bindEvent(element, handler) { ... };` and pass the element and the event handler to the function. Here is an example: http://stackoverflow.com/questions/5411055/javascript-multiple-event-listeners-handlers-on-the-same-element/5411130#5411130. – Felix Kling Feb 25 '13 at 22:57
  • So it's considered bad practice unless you're doing what jQuery does and returns the prototype on the created jQuery object with custom methods on the object itself due to the fact no two browsers are the same in what methods are exposed (as shown in IE) so for guaranteed results it's recommended you just use a function? Thanks for the link. – Dwayne Charrington Feb 26 '13 at 00:55
  • Yep. To summarize: jQuery is simply a wrapper, which is perfectly fine. The problem with extending the DOM is that (a) they are host objects, and might behave differently than how objects are defined in the ECMAScript spec and (b) older IE versions don't expose the prototype of DOM nodes. – Felix Kling Feb 26 '13 at 01:43
  • Perfect, thanks Felix. If you had your comments as an answer I'll accept it. – Dwayne Charrington Feb 26 '13 at 01:45
  • Did that and added some more info which is hopefully helpful :) – Felix Kling Feb 26 '13 at 02:00

2 Answers2

4

Extending the prototype of DOM elements is an even worse idea than extending built-in objects . Please have a look at the article "What's wrong with extending the DOM".

What jQuery provides is a simple wrapper around the DOM API, which is ok. The problem with extending the DOM is that

  • they are host objects, and might behave differently than how objects are defined in the ECMAScript spec and
  • older IE versions don't even expose the prototype of DOM nodes.

The reason I am doing this is I am trying to create a cross-browser implementation of attaching events without having to do if statements all of the time.

This alone is no reason to extend the DOM. You can define your own function which binds event handlers and you even have to test whether addEventListener or attachEvent exists only once on page load. Such a function could look like this:

var bindEvent = (function() {
    if (document.addEventListener) {
        return function(element, event, handler) {
            element.addEventListener(event, handler, false);
        };
    }
    else {
        return function(element, event, handler) {
            element.attachEvent("on" + event, function() {
                handler.call(element, window.event);
            }
        };
    }
}());

You can put a lot of normalization into such a function. For example, when using attachEvent, this does normally not refer to the element the handler is bound to (it refers to window), unlike with addEventListener. Also, as you might know, the event object is not passed as argument to the handler in IE. Both of these issues have been solved through the line:

handler.call(element, window.event);

(the disadvantage is that you cannot simply remove the handler, since you didn't bind handler directly, but these problems can be solved as well).

You can find more information about these browser differences and more in the excellent articles at quirksmode.org.


†: Since browsers provide Object.defineProperty and hence the possibility to mark properties as non-enumerable, extending built-in objects is not as bad anymore, but if libraries start using this, the chance of name collisions, method overriding and incompatibilities gets higher.
For your own code it should be ok. DOM objects should still be a tabu.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • This is a mighty fine answer, thanks Felix. I'm sure it'll help many wanting jQuery like syntax and hopefully make them think twice (like I did). – Dwayne Charrington Feb 26 '13 at 05:35
0

If I understood correctly, you want to know how to add methods to the built in javascript objects, so:

myObject.prototype.myMethod = function() {
  // whatever
}

so, by example:

String.prototype.splice = function() {
// splice function for every string
}
martriay
  • 5,632
  • 3
  • 29
  • 39