Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference of the value, prototype and property

OK! First of all this question comes from a man who digs too deep (and posibly get lost) in the jQuery universe.

In my reserch I discovered the jquery's main pattern is something like this (If needed correction is wellcomed):

(function (window, undefined) {

   jQuery = function (arg) {
      // The jQuery object is actually just the init constructor 'enhanced'
      return new jQuery.fn.init(arg);
   },
   jQuery.fn = jQuery.prototype = {
      constructor: jQuery,
      init: function (selector, context, rootjQuery) {
         // get the selected DOM el.
         // and returns an array
      },
      method: function () {
         doSomeThing();
         return this;
      },
      method2: function () {
         doSomeThing();
         return this;,
         method3: function () {
            doSomeThing();
            return this;
         };

         jQuery.fn.init.prototype = jQuery.fn;

         jQuery.extend = jQuery.fn.extend = function () {

            //defines the extend method 
         };
         // extends the jQuery function and adds some static methods 
         jQuery.extend({
            method: function () {}

         })

      })

When $ initiates the jQuery.prototype.init initiates and returns an array of elements. But i could not understand how it adds the jQuery method like .css or .hide ,etc. to this array.

I get the static methods. But could not get how it returns and array of elements with all those methods.

like image 631
Lupus Avatar asked Aug 27 '12 14:08

Lupus


2 Answers

I don't like that pattern either. They have an init function, which is the constructor of all jQuery instances - the jQuery function itself is just a wrapper around that object creation with new:

function jQuery(…) { return new init(…); }

Then, they add the methods of those instances to the init.prototype object. This object is exposed as an interface at jQuery.fn. Also, they set the prototype property of the jQuery function to that object - for those who don't use the fn property. Now you have

jQuery.prototype = jQuery.fn = […]init.prototype

But they also do two [weird] things:

  • overwriting the constructor property of the prototype object, setting it to the jQuery function
  • exposing the init function on jQuery.fn - its own prototype. This might allow Extending $.fn.init function, but is very confusing

I think they need/want to do all this to be fool-proof, but their code is a mess - starting with that object literal and assigning the init prototype things afterwards.

like image 179
Bergi Avatar answered Nov 02 '22 11:11

Bergi


It’s easier to digest if you think of the API as an external collection of methods, and the jQuery function as the wrapper.

It’s basically constructed like this:

function a() { return new b();}
a.prototype.method = function() { return this; }
function b() {}
b.prototype = a.prototype;

Except that a is jQuery and b is jQuery.prototype.init.

I’m sure Resig had his reasons for placing the api constructor in the init prototype, but I can’t see them. A couple of more strangeness besides the ones Bergi mentioned:

1) The patterns requires a reference copy from jQuery.fn.init.prototype to jQuery.prototype, wich allows a weird endless loop:

var $body = new $.fn.init.prototype.init.prototype.init.prototype.init('body');

2) Every jQuery collection is actually an instance of jQuery.fn.init, but since they reference the same prototype object, it tricks us to "think" that the collection is an instance of jQuery. You can do the same sorcery like this:

function a(){}
function b(){}
a.prototype = b.prototype;
console.log( new b instanceof a); // true
console.log( new a instanceof b); // true

Sidenote: I have personally used the following constructor pattern with similar results without the weirdness:

var a = function(arg) {
    if (!(this instanceof a)) {
        return new a(arg);
    }
};
a.prototype.method = function(){ return this; };
like image 30
David Hellsing Avatar answered Nov 02 '22 10:11

David Hellsing