11
votes

Créer une jQuery comme "$" objet "

Mon objectif final est de pouvoir faire quelque chose comme ceci: xxx

assez idiot, même après avoir lu comment les variables sont déclarées, en regardant le code JQuery, ... je suis toujours Je ne peux pas avoir la tête autour de ça.

C'est ce que j'ai essayé jusqu'à présent, mais il échoue: xxx


3 commentaires

Test (...) n'est pas le même que Nouveau test (...) . :)


J'ai écrit un article décrivant le concept de création de ce type de bibliothèque simple: DFSQ.INFO/ Site / lecture / écriture-votre-propre-jQuery


Voir ma réponse pour Simple bibliothèque JavaScript comme JQuery


8 Réponses :


1
votes

Lorsque vous faites xxx

Vous créez un objet qui a deux attributs déplacer et impression . Votre objet test n'est plus une fonction en raison de la relève nouvelle . Alors appeler test () est faux.


1 commentaires

Appelant Test (). Déplacer () est faux si vous essayez d'instancier un objet objet , mais enchaînant les appels de fonction (la clé de la mise en œuvre de JQuery) est très possible.



0
votes

Vous pouvez transmettre la valeur 'Azerty' comme paramètre sur MyClass Constructor et modifier le test ('azerty'). Déplacez () sur Test.Move ()

<script type="text/javascript">
    var MyClass = function(context) { 
        this.print = function(){     
            console.log("Printing"); 
        }  
        this.move = function(){     
        console.log(context); 
        return context;
        } 
    };  
    var test = new MyClass('azerty'); 
    test.print(); // Works 
    console.log('Moving: ' + test.move() ); // Type property error 
</script>


0 commentaires

1
votes

Chaque fois que vous appelez $ code> dans jQuery, il renvoie un nouveau jQuery.init code> objet. L'objet jquery.init code> a des fonctions qui sont ensuite appelées.

test.a.prototype.move = function()
{
  //move function defined for the a object
  return this;
};


0 commentaires

14
votes

jQuery () code> est à la fois un module avec des méthodes globales et un constructeur. Il appelle automatiquement un constructeur s'il doit. Si nous ne sommes pas appelés avec un mot-clé code> neuf code>, alors ceci code> n'aura pas été construit avec myClass code>. Nous pouvons détecter cela et appeler la fonction en mode constructeur à la place. Une fois que nous faisons cela, alors ceci code> sera une instance de myClass code> et nous pouvons commencer à ajouter des trucs.

var MyClass = function(context) {
    // if the function is called without being called as a constructor,
    // then call as a constructor for us.
    if (this.__proto__.constructor !== MyClass) {
        return new MyClass(context);
    }

    // Save the context
    this.context = context;

    // methods...
    this.print = function() {
        return "Printing";
    }

    this.move = function() {
        return this.context;
    }
};

$('#output').append('<li>print(): '+ MyClass().print() +'</li>');
$('#output').append('<li>move():'+ MyClass('azerty').move() +'</li>');
$('#output').append('<li>context: '+ MyClass('azerty').context +'</li>');


3 commentaires

Maintenant je comprends. Il doit encore être instancié, mais cela peut être fait de l'intérieur. Jolie cool, merci!


Heureux d'aider! De plus, je viens de mettre à jour ma réponse avec une meilleure façon de détecter s'il s'agissait d'appelé constructeur ou non en vérifiant en réalité le constructeur du prototype de Ceci . Devrait être beaucoup plus robuste.


Même si cela fonctionne comme je le souhaite, je viens de comprendre que (parce que c'est instancié pour chaque appel de myClass (), il est assez lent pour mon but. Vous vivez et apprenez: p



17
votes

Comme j'écris ceci, la réponse de Squeegy a le plus grand nombre de votes: 7. Pourtant, il est faux parce que __ proto __ est non standard et n'est pas pris en charge par Internet Explorer (même la version 8). Cependant, se débarrasser de __ proto __ ne fonctionne pas non plus dans IE 6.

Ceci (un peu simplifié) est la façon dont JQuery le fait effectivement ( Essayez même sur IE 6 ), et il comprend également des exemples de méthodes statiques et de chaînage de méthode. Pour tous les détails de la façon dont JQuery le fait, bien sûr, vous devrez vérifier le JQuery Source Code vous-même. xxx

Notez que si vous avez besoin de données" privées ", vous devrez mettre des méthodes d'instance à l'intérieur MyClass. init (avec une variable déclarée juste à l'intérieur de cette fonction) comme this.print = fonction () {...}; au lieu d'utiliser myclass.init.pototype .


0 commentaires

1
votes

[probablement] la solution la plus élégante

Tout d'abord, jQuery utilise un motif qui est plus proche d'un monad , un usine ou une combinaison des deux. Néanmoins, voici ce que j'utilise dans mes projets car le motif, lui-même, est tellement associé à la classe que vous souhaitez utiliser: xxx

essentiellement, vous peut l'utiliser comme une fonction, un objet et d'utiliser le mot-clé nouveau pour construire un autre objet / fonction unique. Vous pouvez l'utiliser pour appliquer une méthode arbitre (par défaut, comme la méthode Rechercher ci-dessus) ou utilisez différentes méthodes sur la base de quels paramètres sont entrés. Par exemple, vous pouvez faire quelque chose comme: xxx

- ou - xxx

Ce serait, par exemple , accumulez une nodéliste de plusieurs éléments (1ère expression), ou percez jusqu'à un élément spécifique (2e).

espère que cela aide


0 commentaires

1
votes

J'ai récemment travaillé sur un exercice qui a demandé de recréer une bibliothèque de jQuery comme uniquement en utilisant ES6.

à partir des points ci-dessus, j'ai pu créer la logique d'instanciation permettant d'appeler des méthodes sur les noms de classe Selectors E.g. p>

Lorsque l'instance de $ T est appelée avec un sélecteur, une nouvelle instance de TLIB $ est créée sur le sélecteur particulier qui contiendra toutes les méthodes pouvant être utilisées sur le sélecteur avec les éléments en contexte . P>

J'ai ajouté quelques méthodes qui sont chaînées dans l'exemple ci-dessous qui vous permet d'ajouter une classe CSS à un élément et de supprimer la même classe dans un appel, par exemple: P>

const $T = (selector) => {
  // returns the HTML elements that match the selector
  const elements = document.querySelectorAll(selector);
  return new $TLib(elements, selector);
};

class $TLib {
  constructor (elements) {
    this._elements = elements;
  }

  addClass (className) {
    this._elements.forEach((element) => element.classList.add(className));
    return this;
  }

  removeClass (className) {
    this._elements.forEach((element) => element.classList.remove(className));
    return this;
  }

  toggleClass (className) {
    this._elements.forEach((element) => {
      const classList = element.classList;
      (classList.contains(className)) ? classList.remove(className) : classList.add(className);
    });
    return this;
  }

}


0 commentaires

0
votes

Les solutions fournies jusqu'à présent ne semblent pas refléter la structure exacte de JQuery (ou JQuery changé au fil du temps).

Je voulais récemment créer un objet (semblable à JQuery) et je suis tombé sur cette question. Alors voici ma réponse: p>

p>

// dummy text element 
var p = document.createElement("p");
p.innerText = "Lorem ipsum...";


// jQuery-like object
var CustomObject = function (element) {
    return new CustomObject.prototype.init(element);
};

// constructor
CustomObject.prototype.init = function (element) {
    this.el = element;
    this.text = element.innerText;
};

// instance methods
CustomObject.prototype.log = function () {
    console.log(this.text);
    // by returning "this" at the end of instance methods
    // we make these methods chainable
    return this;
};

CustomObject.prototype.add2body = function (delay) {
    document.body.appendChild(this.el);
    return this;
};

// all the instance methods are added to CustomObject, not to CustomObject.init (constructor)
// calling CustomObject() returns a CustomObject.init object, not CustomObject object
// so by default, instance methods are not accessible
// to fix this, you need to assign the prototype of CustomObject to CustomObject.prototype.init
CustomObject.prototype.init.prototype = CustomObject.prototype;

// testing
var obj = CustomObject(p).add2body().log();


0 commentaires