There is no such thing as a JavaScript plugin

One thing that you often hear people say about jQuery is that is has a neat plugin mechanism. It’s true there are a great many useful plugins available for jQuery and it makes them super-easy to write, but I want to let you in on a little secret:

jQuery.fn = jQuery.prototype;

That is jQuery’s plugin mechanism in its entirity. Now my point here is not that jQuery somehow sucks (far from it) but that I suspect many folks could use JavaScript better if they understood how flexible it is. In jQuery’s case, the $() function returns an instance of the jQuery class, so if you add methods to jQuery.prototype then you can use those methods to change elements in new and exciting ways. Behold:

$.fn.makeThemRed = function() {
  this.css({color: 'red'});
  return this;
};

$('p').makeThemRed();

$.fn is just a shorter alias for jQuery.prototype. The really important thing here is that there is nothing special about the jQuery class: all objects (including prototypes) are extensible in JavaScript, and you can add and remove properties and methods from any object whenever you like. Of course, the effect of changes you make to a given object are entirely up to you, the point is that you are allowed to make such changes.

One consequence of this is that you can modify the behaviour of existing methods in any library you happen to be using. Take this snippet from Reiterate, which adds new behaviour to a stack of Enumerable methods in Prototype:

[Enumerable, Array.prototype, Hash.prototype,
ObjectRange.prototype, Ajax.Responders,
Element.ClassNames.prototype].each(function(object) {

  $w('each all any collect detect findAll max \
  min partition reject sortBy map find select \
  filter every some').each(function(method) {

    if (!object[method]) return;
    var wrapped = object[method];
    object[method] = function() {
      var args = $A(arguments);
      if (args[0]) args[0] = Function.from(args[0]);
      return wrapped.apply(this, args);
    };

  });
});

This loops over all objects that include Enumerable, and loops over the list of modified methods for each object. For example, lets’s expand it for the modification of Enumerable.collect to make it a little clearer:

    var wrapped = Enumerable.collect;
    Enumerable.collect = function() {
      var args = $A(arguments);
      if (args[0]) args[0] = Function.from(args[0]);
      return wrapped.apply(this, args);
    };

So we store a reference to the original implementation of Enumerable.collect, then redefine it. Our new function can call the original function after modifying the arguments a little - it effectively acts as an input filter. Some parts of this implementation (each(), $w(), $A()) are provided by Prototype but the core idea - the method interception - is pure JavaScript. Next time you’re using a fancy language feature provided by your favourite library, take a look at how it’s implemented; you’ll probably find the implementation is trivial and you might learn a little about JavaScript’s power.







6 Responses to “There is no such thing as a JavaScript plugin”

[...] There is no such thing as a JavaScript plugin contends James Coglan. I completely agree that there are no, specific, techniques within the JavaScript language that make “plugins” possible (such as the ability to namespace code and import it, or some such). [...]

John Resig - jQuery Plugins, Size, and Storage added these pithy words on Jul 02 08 at 8:03 pm

[...] Coglan wrote a piece on There is no such thing as a JavaScript plugin that uses jQuery as a use case for how simple it is to have a plugin [...]

Ajaxian » JavaScript Plugins; The beauty of loosely coupled code added these pithy words on Jul 03 08 at 3:16 pm

Isn’t what you’re talking about just monkey patching? It’s a practice well known to have a variety of issues.

Mike Lin added these pithy words on Jul 03 08 at 10:16 pm

Mike, that’s precisely what it is. Whether you use it or not is a design decision for you to make. Me, I like my languages to give me enough rope to hang myself rather than trying to stop me shooting myself in the foot. Rails’ vast plugin ecosystem (and I would hesitate to call them plugins, both for the reasons given above and for the fact that many of them would fail even to meet John Resig’s definition) would not be anything like as rich were it not for Ruby’s flexibility.

James added these pithy words on Jul 03 08 at 10:37 pm

[...] The If Works » Blog Archive » There is no such thing as a JavaScript plugin “t’s true there are a great many useful plugins available for jQuery and it makes them super-easy to write, but I want to let you in on a little secret: [...]

links for 2008-07-06 « Talkabout added these pithy words on Jul 06 08 at 3:32 am

[...] - bookmarked by 4 members originally found by jau on 2008-07-28 There is no such thing as a JavaScript plugin http://blog.jcoglan.com/2008/07/02/there-is-no-such-thing-as-a-javascript-plugin/ - bookmarked by [...]

Bookmarks about Thumbnail added these pithy words on Aug 15 08 at 5:45 am

Leave a Reply