Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does jQuery have the $ object constructor and the methods associated with the $?

How is it that jQuery can do $("#foo").addClass("bar") and $.ajax()?

I'm creating a micro javascript framework and want to create a new instance of an object, such as $("#hello"). With this object there are associated methods, such as addClass, css, etc, just like with jQuery. So I could do something like

$("#foo").addClass("remove").css("color", "red");

I have been successful in creating this. However, when I want to call a method from this object, such as $.ajax, the constructor function is overwritten, and I can call $.ajax, but not $("#foo").

Basically, how can jQuery do both?

like image 611
angus Avatar asked Jun 11 '11 00:06

angus


People also ask

What is constructor in jQuery?

A constructor is a function that creates an instance of a class which is typically called an “object”. In JavaScript, a constructor gets called when you declare an object using the new keyword. The purpose of a constructor is to create an object and set values if there are any object properties present.

Which methods returns the element as a jQuery object?

get()Returns: Array. Description: Retrieve the elements matched by the jQuery object.

What does $() mean in jQuery?

In jQuery, the $ sign is just an alias to jQuery() , then an alias for a function. This page reports: Basic syntax is: $(selector).action() A dollar sign to define jQuery. A (selector) to "query (or find)" HTML elements.


2 Answers

$ = function(arg) { console.log("$ function called with " + arg); }
$.ajax = function(arg) {console.log("$.ajax called with " + arg);}
$('foo');
$.ajax('bar');

http://jsfiddle.net/ac7nx/

I don't think there's any magic here. $ is just a name for the global function. Just keep in mind that in javascript, functions are first class objects that can have their own properties, including sub-functions, which is what $.ajax is.

Since you mentioned the constructor function, I should note that there are no OO objects being used here, just regular functions (no new keyword), so constructor functions don't play into this. If you are using the new keyword, that is probably where you are getting confused. If you want $('#foo') to return a new object, then inside the $ function's code you should create a new object using new and return that, which is what jQuery does, but the $ function itself is not a constructor and should not be called with new. Or in the case of something like $('#someID'), inside that function jQuery is getting an element object from the DOM and then returning that object, but still $ is just a regular function whose return value is an object, not a constructor function.

like image 57
Peter Lyons Avatar answered Oct 05 '22 23:10

Peter Lyons


OK, the $ function is not only a function but an object, like all functions. So it can have methods. That's all that ajax is, a method of the $ function. So we can start off by doing this:

$ = function(obj) {
  // some code 
};
$.ajax = function (arg1, arg2) {
  // some ajax-y code
};

So far so good. Now, what on earth do we put in the $ function? Well it has to return an object and that object has to have some nice methods defined on it. So we'll need a constructor function (to give us new objects) and a prototype (to provide the nifty methods for those objects).

$ = function(obj) {
  var myConstructor = function (obj) {
    this.wrappedObj = obj;
  };

  myConstructor.prototype = {
    niftyMethod: function () {
      // do something with this.wrappedObj
      return this; // so we can chain method calls
    },
    anotherNiftyMethod: function (options) {
      // do something with this.wrappedObj and options
      return this; 
    }
  };

  return new myConstructor(obj);
};

So there we have it. We can do this:

var mySnazzObject = $("whatever");
mySnazzObject.niftyMethod().anotherNiftyMethod(true);        

And we can do this:

$.ajax("overthere.html", data);

Obviously jQuery does a heck of a lot more than that, and it does it in some really impressive ways, but that's the general idea.

UPDATE: AS @Raynos was kind enough to observe without supplying a constructive answer, my original code would create the prototype ad infinitum. So we make use of an anonymous autoexecuting function to declare the constructor and prototype separately:

(function () {
  var myConstructor = function (obj) {
    this.wrappedObj = obj;
  };

  myConstructor.prototype = {
    niftyMethod: function () {
      // do something with this.wrappedObj
      return this; // so we can chain method calls
    },
    anotherNiftyMethod: function (options) {
      // do something with this.wrappedObj and options
      return this; 
    }
  };

  var $ = function(obj) {
    return new myConstructor(obj);        
  };

  $.ajax = function (arg1, arg2) {
    // some ajax-y code
  };

  window.$ = $;  
}());
like image 33
jmbucknall Avatar answered Oct 06 '22 00:10

jmbucknall