2

I've been programming in JavaScript for a couple of years, but I've never understood how different techniques work in JavaScript, only that it works..

Now, after learning properly how prototypes and constructors work, I took a look at jQuery to learn something before I set out to make my own (not publicly accessible) plugin for my own website.

The problem is just that I don't understand how it works. Here is a almost working sample: http://jsfiddle.net/3zWvR/1/

(function() {
    test = function(selector) {
        return new test.prototype.init(selector);
    }
    test.prototype = {
        init: function(selector) {
            alert("init ran");
            if (!arguments[0]) {
                return this;
            }
        }
    }
 // As I understand the jQuery code, the next line should really be
 // test.prototype = {
    test.prototype.init.prototype = {
        send: function() {
            alert("send ran");
        }
    }

    window.ob = test;
})()

ob().send();​

I've commented a line in there that shows what I think really should be there if I do it like jQuery. But I'm not able to replicate it so that you could do ob.method() either...

How is the jQuery "framework" or skeleton built and how does it work?

Student of Hogwarts
  • 1,108
  • 3
  • 14
  • 28
  • 6
    you of all should know the answer to this: it's magic! – Abhilash Nov 21 '12 at 07:17
  • @Abhilash You wouldn't believe me if I told you how many have made jokes about my nickname! xD – Student of Hogwarts Nov 21 '12 at 07:18
  • 2
    You might be interested in this: [Paul Irish on jQuery](http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CDQQFjAA&url=http%3A%2F%2Fpaulirish.com%2F2010%2F10-things-i-learned-from-the-jquery-source%2F&ei=aICsUNTJBbHciQKD8YHQCw&usg=AFQjCNGdORx-aMY9iSzUuF-5SqUnymJP4A&sig2=XFQvBDlkywL8QdC-sjpdWA) – Sdedelbrock Nov 21 '12 at 07:19
  • 1
    And this is a really good tutorial on advanced javascript (from the creator of jQuery) [advanced javascript](http://ejohn.org/apps/learn/) – Sdedelbrock Nov 21 '12 at 07:21
  • 1
    @Sdedelbrock the video is very useful, but he says nothing about this issue – Vithozor Nov 21 '12 at 10:59

1 Answers1

3

Well, your question is very interesting, and it's something that has been on my head since I started to look at the source code of jQuery. Your code should work as you wanted to if you add this:

test.prototype.init.prototype = test.prototype;
test.send = test.prototype.send = function(){
  alert("send ran");
};

instead of this:

test.prototype.init.prototype = {
  send: function() {
    alert("send ran");
  }
};

You are probably saying "I already know that, you are just adding the method send() to the test object and to the prototype of itself", but doing it this way, you are doing exactly what you want: make that ob, ob() and all the variables created with it, like var somevar = ob() have the method send().

If you take a look at the jQuery source code, they use the method extend() to extend the jQuery object. Looking at some of the .extend() calls, you will see that if one method/property is added only to the jQuery.fn object (that is a shorthand to the prototype), the jQuery object doesn't have that method/property. You can see this if you type in a console jQuery.off, it will return undefined, but the method off exists in the jQuery.fn object (type jQuery.fn.off in a console and you will see it).

If you think in jQuery, when you write a plugin, you start by doing jQuery.fn.plugin =, so you add your plugin to the objects created by jQuery, but your plugin is not accessible directly from jQuery.

Think of jQuery as a constructor that also has a lot of utilities. The object returned when you do $(selector) have all the methods in jQuery.fn but not all of the jQuery object, only the ones that they have added into the jQuery.fn.

Vithozor
  • 610
  • 10
  • 22
  • 1
    @Jordi I'm sure you will be there the next time to point it if I fail again. – Vithozor Nov 21 '12 at 14:53
  • This is a great answer! Do you know how they've implemented private functions as well? So they can be called from the inside, but not from the outside? – Student of Hogwarts Nov 21 '12 at 16:16
  • And is the extend-method adding the new methods to both the jQuery object and to the jQuery.prototype.init object? – Student of Hogwarts Nov 21 '12 at 16:20
  • It's not private, it's the same case as when you add something to te `String` object, i.e `String.prototype.returnTrue = function(){return "true"};`, the function is accessible in all the string objects, but not in the `String` object – Vithozor Nov 21 '12 at 16:21
  • No, if you look at the code, you will see some `jQuery.extend(...` and some `jQuery.fn.extend(...`. If I'm not wrong, the `jQuery.fn.init` is just the real constructor of all `jQuery` objects, and they added the line `jQuery.fn.init.prototype = jQuery.fn` to make all `jQuery` objects be instances of `jQuery` itself. – Vithozor Nov 21 '12 at 16:24
  • Oh, I mean, jQuery has lots of methods that aren't callable via $.privateMethod(). Do you know how that is implemented? Is this: http://jsfiddle.net/3zWvR/2/ how jQuery in a simplified form is implementing it? – Student of Hogwarts Nov 21 '12 at 16:24
  • But they are callable via jQuery.privateMethod() or similar inside the closure. – Student of Hogwarts Nov 21 '12 at 16:28
  • Are they really doing this just to enable us to use $.ajax() instead of $().ajax()? – Student of Hogwarts Nov 21 '12 at 16:31
  • The `ajax` method is only available in the `jQuery` (or $) object. If you try to do `$(selector).ajax` it returns `undefined`. You have to think of `jQuery` as an object with a set of methods and properies, that also is a constructor, and the objects returned by that constructor have another set of methods and properties, but different from the `jQuery` ones. Maybe some of the methods in `jQuery` are accessible in the constructed objects, but to achieve that, the developers had to extend the prototype of `jQuery` to expose those methods to the constructed objects – Vithozor Nov 21 '12 at 16:37
  • Hmm, I'm trying to learn something from this to apply to my own JS-code. Do you know how one can have private methods? The jQuery approach is a bit overwhelming for 10 small plugins I'm writing.. And the jQuery approach I see now is made to allow the plugin to differenciate between $.method() and $().method().. – Student of Hogwarts Nov 21 '12 at 17:17
  • If you are interested in private methods in javascript, i recomend you [this page](http://javascript.crockford.com/private.html) from Crockford's page and [this question](http://stackoverflow.com/questions/55611/javascript-private-methods) on Stack Overflow, they are very well explained. Hope it helps :D – Vithozor Nov 22 '12 at 07:11
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/19935/discussion-between-victor-and-student-of-hogwarts) – Vithozor Nov 22 '12 at 11:55