0

Recently I was playing around with writing a small library for music theory in JS. One of the features I wanted to add was a jQuery style selector for creating/finding notes. For example:

Notes("a#") === Note {_note: 0, accidental: 1}

However, the structure of the library looked something akin to:

var Notes = function(sel) {

   // initialisation stuff
   var Note = function() {
        // stuff for note objects
   };

   var scales = {
       ...
   };

   var selector(sel) {
        // evaluate sel
        return new Note(...);
   };

   if(sel !== undefined) {
       return selector(sel);
   }

   return {
       Note: Note,
       scales: scales
   };
};
module.exports = new Notes();

This way, I could use the library like this:

var Notes = require("Notes");
Notes.scales.major.c === [0,2,4,...];

But not like this:

var thisNote = Notes("A#");

As Notes was obviously an object that had been returned from the original Notes function. To use the selector function I'd have to expose it and then call it like this:

var thisNote = Notes.selector("A#");

But I want to mimic the jQuery/sizzle style (I had a bit of a search of jQuery's source, but couldn't find anything that helped).

How can I/should I have approached the design to allow for this kind of functionality? Would using prototypes instead of Closures been a more sensical approach? Or should I have aliased the library's name to another method to achieve the desired effect?

Dan Prince
  • 29,491
  • 13
  • 89
  • 120
  • 1
    I think you misunderstand how the jQuery function works. It selects DOM nodes and wraps them. `Notes.selector` is like `$`, but of course don't need to `var $ = new jQuery()` because there already is a (global) instance. – Halcyon Sep 06 '13 at 16:36
  • [window.$ === window.jQuery](https://github.com/jquery/jquery/blob/master/src/jquery.js) right? How does the jQuery function return DOM wrapped nodes when called as a function whilst also providing a series of methods and objects $.ajax etc? – Dan Prince Sep 06 '13 at 16:41
  • `$` is a function, and also an object (because in JavaScript everything is an object). Then it adds a bunch of properties like `extend` and `ajax` and `Deferred`. – Halcyon Sep 06 '13 at 16:45
  • `var foo = function() {alert("foo");}; foo.bar = function() {alert("bar");}; foo(); foo.bar();` – user2736012 Sep 06 '13 at 16:47
  • 1
    [How is jQuery's $ a function and an object?](http://stackoverflow.com/questions/7223585/how-is-jquerys-a-function-and-an-object) – user2736012 Sep 06 '13 at 16:48

1 Answers1

1

jQuery is like this:

function wrap() {
    // do wrapping of DOM nodes
    return {
        value: function () { /*..*/ },
        add_class: function () { /*..*/ }
    };
}
wrap.extend = function () { /*..*/ }
wrap.ajax = function () { /*..*/ }

wrap("#abc"); // has `.value` and `.add_class)
wrap.ajax();
Halcyon
  • 57,230
  • 10
  • 89
  • 128
  • That's perfect, thanks. Out of interest is there any way to create the same effect with closures and aliasing? – Dan Prince Sep 06 '13 at 16:50
  • You can add a closure if you want, if for instance want to share functions between `.extend` and `.ajax`. It's not essential though. – Halcyon Sep 07 '13 at 14:54