29 votes

Comment jQuery peut-il se comporter comme un objet et une fonction?

jQuery ou $ semble être une fonction:

 typeof $; // "function"
 

Et il agit comme un seul:

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

Mais quand je laisse tomber la fonction entre parenthèses, elle se comporte comme un objet:

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

Je voudrais savoir comment cela est possible et comment je peux implémenter ce comportement à mes propres fonctions.

33voto

Rob W Points 125904

Les fonctions sont des objets, de sorte $.each peuvent être définies de la même façon qu'un Objet.

JavaScript est un prototype de la langue. Pour jQuery, cela signifie que chaque instance de $ hérite des méthodes d' jQuery.prototype.Voir Les Notes

Une ébauche de démonstration, pour atteindre le même comportement:

(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 racine de la méthode est définie comme suit (seulement relevants pièces sont indiquées):

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

L'avantage de l' prototype méthode est qu'il est très facile de la chaîne des méthodes et des propriétés. Par exemple:

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

Une méthode pour mettre en œuvre cette fonctionnalité pourrait être:

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

Si vous êtes intéressé par jQuery réel de la mise en œuvre, ont un coup d'oeil à la annotée du code source:

10voto

recursive Points 34729

Toutes les fonctions fonctionnent de cette façon.

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

fn.foo = "bar";
 

3voto

dgvid Points 10847

En JavaScript, les fonctions sont un type d'objet. Plus précisément, les fonctions sont des instances de la Fonction de l'objet qui est dérivé de l'Objet. jQuery prend avantage de cette réalité et se bloque certains "statique" des méthodes à partir de la fonction jQuery objet.

jQuery créateur John Resig a un bon tutoriel sur ce sujet http://ejohn.org/apps/learn/. Qui pourrait vous donner quelques idées sur la façon de tirer parti de cette fonctionnalité de JavaScript dans votre propre code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X