Authentification dans un module RequireJS

Tout d'abord, je ne suis pas sûr que ce soit la bonne façon d'utiliser cette bibliothèque. Je voudrais définir plusieurs fonctions / méthodes statiques dans un module et les utiliser dans la portée du module. Par exemple:

define({ foo: function() { return "Hello"; }, bar: function() { alert( this.foo() ); } }); 

Main.js

 require( ['foobar'], function( foobar) { foobar.bar(); // works $('body').click( foobar.bar ); // crash - Object #<HTMLBodyElement> has no method 'foo' }); 

Ce code ne fonctionnera pas si bar() est déclenchée par un événement car, évidemment, this signifie quelque chose de différent dans cette portée. Existe-t-il une variable globale qui se réfère à l'objet défini et me permettra d'accéder aux méthodes et aux attributs à l'intérieur du code define() ?

EDIT: Pour plus d'informations, consultez ci-dessous.

Vous pouvez avoir une portée interne en utilisant une fonction. Vous pouvez déclarer votre module comme ceci:

 define((function () { var self = { // this line is changed foo: function() { return "Hello"; }, bar: function() { alert( self.foo() ); } }; return self; }())); // and this 

Cela semble terrifiant, je le reconnais. Point est, il stocke une référence à l'objet que vous renvoyez, et l'utilise pour appeler foo . Je ne sais pas si vous voulez que ce soit comme ça … Mais ça marche.


REMARQUE: Cette partie traite de la gestion de this dans JS. Voir le commentaire pour lequel cette question n'est plus pertinente pour cette question.

Le problème est en fait dans main.js , pas dans votre module. Le problème est de savoir comment JS gère this . Ce n'est pas le même que dans la plupart des autres langues! this dans JS est le contexte dans lequel la fonction est appelée , pas dans laquelle elle est définie . Vous pouvez apply fonctions à d'autres objets, même sans avoir cette fonction.

Dans votre cas, vous souhaitez bind bar à votre objet foobar , de sorte que le bar est l'objet correct. Vous utilisez la bind fonction pour cela. Il crée une nouvelle fonction avec le contexte défini sur l'objet que vous avez spécifié. Exemple:

 function doubleMe () { return this * 2; } 

Vous pouvez appeler cette fonction en procédant comme suit:

 doubleMe.apply(5) // returns 10 

Vous pouvez également le faire:

 var giveMeTen = doubleMe.bind(5); 

Maintenant giveMeTen est une fonction qui retourne 10 si elle est exécutée. Je vous encourage à lire plus sur ce sujet, la manipulation de this est étrange d'abord, mais belle si elle est comprise 😉


En ce qui concerne votre code, je voudrais écrire:

 require( ['foobar'], function( foobar) { foobar.bar(); $('body').click( foobar.bar.bind(foobar)); }); 

Notez que jQuery définit this à l'élément qui a été cliqué sur le gestionnaire de click() .

Je ne suis pas sûr de ce que vous essayez d'accomplir ici, peut-être avec plus de contexte que ce que vous essayez de faire, nous pourrions vous donner un conseil plus précis.

Néanmoins, voici comment je fais généralement des modules avec requireJS (classes, principalement)

 if ( typeof define === "function" && define.amd ) { define( "module", function () { var MyModule = function(){ this.foo = function(){ return "Hello!"; }; this.bar = function(){ return this.foo(); }; } return MyModule; }); } 

Et maintenant, utiliser:

 require("module", function(MyMod){ var a = new MyMod(); console.log(a.bar()); } 

J'espère que cela t'aides. (Vous pouvez probablement deviner comment faire des singletons à partir de ceci en utilisant une portée fermée)

Cela peut se faire en passant une fonction à définir (cette fonction s'appelle une fonction de définition). À l'intérieur de la fonction de définition:

  1. Définissez les fonctions que vous souhaitez utiliser dans le module.
  2. Assurez-vous que la fonction de définition renvoie un objet avec la fonctionnalité que vous souhaitez que le module expose. Ici, dans l'objet que vous retournez, vous pouvez appeler les fonctions définies à l'étape précédente.

     define(function() { function foo() { return "Hello"; }; return { bar: function() { alert(foo()); } } });