How can jQuery behave like an object and a function?

a 夏天 提交于 2019-12-17 07:22:35

问题


jQuery or $ seems to be a function:

typeof $; // "function"

And it acts like one:

$('div').removeClass(); // $ constructs a new object with some methods like removeClass

But when I drop the function parentheses it behaves like an object:

$.each(/* parameters */); // $ is an object with some methods like each

I'd like to know how this is possible and how I can implement this behaviour to my own functions.


回答1:


Functions are also objects, so $.each can be defined in a similar way as an Object.

JavaScript is a prototypical language. For jQuery, this means that every instance of $ inherits methods from jQuery.prototype.See Notes

A very rough demo, to achieve the similar behaviour:

(function() { // Closure to not leak local variables to the global scope
    function f(a, b) {
        //Do something
    }
    // Prototype. All properties of f.prototype are inherited by instances of f.
    // An instance of f can be obtained by:    new f, new f(), Object.create(f)
    f.prototype.removeClass = function(a) {
        return a;
    };
    function $(a, b) {
        return new f(a, b); // <--- "new f" !  
    } 
    $.each = function(a) {
        alert(a);             
    };
    window.$ = $; // Publish public methods
})();

//Tests (these do not represent jQuery methods):
$.each("Foo");                   // Alerts "Foo" (alert defined at $.each)
alert($().removeClass('Blabla'));// Alerts "Blabla"

Notes

jQuery's root method is defined as follows (only relevants parts are shown):

(function(win) {
    var jQuery = function (selector, context) {
        return new jQuery.fn.init(selector, context, rootjQuery);
    };
    //$.fn = jQuery.fn is a shorthand for defining "jQuery plugins".
    jQuery.fn = jQuery.prototype = {
        constructor: jQuery,
        init: function( /* ..parameters.. */ ) { 
            //.... sets default properties...
        }
        //....other methods, such as size, get, etc...
        //.... other properties, such as selector, length, etc...
    };
    jQuery.fn.removeClass = function() { // (Actually via jQuery.fn.extend)
        // ... method logic...
    };  //...lots of other stuff...

    win.$ = win.jQuery = jQuery; //Publish method
})(window);

The advantage of the prototype method is that it's very easy to chain methods and properties. For example:

$("body").find("div:first").addClass("foo");

A method to implement this feature could be:

$.fn.find = function(selector) {
    ...
    return $(...);
};

If you're interested in jQuery's real implementation, have a look at the annotated source code:

  • jQuery core - Definitions of the constructor and base methods.
  • jQuery.fn.extend is used to add removeClass, etc. to jQuery.
  • jQuery 1.7.1.



回答2:


All functions work this way.

function fn() {
    alert("hi mom");
}

fn.foo = "bar";



回答3:


In JavaScript, functions are a type of object. Specifically, functions are instances of the Function object which is derived from Object. jQuery takes advantage of that fact and hangs some "static" methods from the jQuery function object.

jQuery's creator John Resig has a nice tutorial on this subject at http://ejohn.org/apps/learn/. That might give you some ideas about how to leverage this feature of JavaScript in your own code.



来源:https://stackoverflow.com/questions/8734115/how-can-jquery-behave-like-an-object-and-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!