Подтвердить что ты не робот

Как jQuery может вести себя как объект и функция?

jQuery или $ представляется функцией:

typeof $; // "function"

И он действует как один:

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

Но когда я отбрасываю круглые скобки функции, он ведет себя как объект:

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

Я хотел бы знать, как это возможно и как я могу реализовать это поведение для своих собственных функций.

4b9b3361

Ответ 1

Функции также являются объектами, поэтому $.each можно определить аналогично объекту.

JavaScript - это прототип языка. Для jQuery это означает, что каждый экземпляр $ наследует методы из jQuery.prototype. См. Примечания

Очень грубая демонстрация, чтобы добиться аналогичного поведения:

(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"

Примечания

Корневой метод jQuery определяется следующим образом (показаны только части релевантов):

(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);

Преимущество метода prototype заключается в том, что очень легко цепочки методов и свойств. Например:

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

Метод реализации этой функции может быть:

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

Если вас интересует реальная реализация jQuery, посмотрите на аннотированный исходный код:

Ответ 2

Все функции работают таким образом.

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

fn.foo = "bar";

Ответ 3

В JavaScript функции являются типом объекта. В частности, функции - это экземпляры объекта Function, который получен из Object. jQuery использует этот факт и использует некоторые "статические" методы из объекта функции jQuery.

Создатель jQuery Джон Ресиг имеет хороший учебник по этому вопросу в http://ejohn.org/apps/learn/. Это может дать вам некоторые идеи о том, как использовать эту функцию JavaScript в вашем собственном коде.