JavaScript perdant cette référence d'objet "this" avec des propriétés privées / publiques

J'ai l'erreur suivante lors de l'exécution de la page ci-dessous:

"This.testpublic n'est pas une fonction"

test = function() { var testprivate = function() { this.testpublic(); } this.testpublic = function() { console.log('test'); } testprivate(); } new test(); 

Apparemment, lorsque testprivate est appelé, "ceci" commence à pointer vers "fenêtre" au lieu de l'objet.

Ne devrait-on pas conserver JavaScript ce contexte dans le même objet?

Vous devez manipuler le contexte lorsque vous appelez testprivate. Vous pouvez utiliser function.call pour remplacer la portée de la fonction. Essaye ça:

 test = function() { var testprivate = function() { this.testpublic(); } this.testpublic = function() { console.log('test'); } testprivate.call(this); } new test(); 

Le problème est que this ne se référait jamais à l'objet de test pour commencer. Il s'agissait toujours de l'objet entourant le plus proche – qui dans ce cas est une window .

 test = function() { var testprivate = function(say) { console.log('test', say); } this.testpublic = function(say) { testprivate('test', say); } testprivate(); } x = new test(); 

Cela fonctionne parce que, si je le comprends bien, this est déterminé au moment de l' appel – et il est verrouillé dans l'objet "entourant" le plus proche *, à moins que l' call() ou l' apply() soit utilisé.

* Il y a probablement un mot beaucoup mieux pour cela, mais je ne le sais pas au sommet de ma tête. Si quelqu'un sait, veuillez nous éclairer tous 🙂

Non, il ne devrait pas. La fonction définit simplement la portée.

Lorsque vous appelez foo.bar() alors this (la bar() intérieure bar() ) est foo . Étant donné qu'il n'y a pas de foo explicite dans ce cas, il s'agit d'une window par défaut.

( this est traité différemment lorsque le new mot-clé est en jeu, mais ce n'est pas pour cet appel)

C'est comme Sean dit: vous ne créez pas réellement une nouvelle référence à un objet (en créant un tel contexte), car vous appelez simplement le constructeur – n'utilisant pas le constructeur pour créer un nouvel objet. Si vous utilisez le nouveau mot-clé, cela fonctionne juste en dur.

Étant donné que la portée de test () est une fenêtre lorsque vous l'appelez, toute fonction appelée dans le test () s'exécutera dans la portée de la fenêtre .

En utilisant le nouveau mot-clé, vous allouez un nouvel objet à la mémoire et créez une nouvelle portée.

Par exemple, essayez ceci en firebug:

 var myFunction = function() { this.memberVariable = "foo"; console.log(this); } myFunction(); console.log(window.memberVariable); var myObject = new myFunction(); console.log(myObject.memberVariable); 

Vous verrez ce résultat:

 Window stats foo Object { memberVariable="foo"} foo 

L'objet de base de la fonction a une méthode, un appel () , qui, comme décrit par Craig, vous permet de spécifier explicitement à quelle portée la fonction devrait s'exécuter:

 var myFunction = function() { this.memberVariable = "foo"; } myFunction.call(myFunction); console.log(myFunction); // "Function()" console.log(myFunction.memberVariable); // "foo" 

Ce n'est cependant pas la manière préférée de faire les choses, car vous ne créez pas vraiment un nouvel objet ici, et typeof myFunction retournera toujours "fonction" au lieu de "objet" – lorsque vous vouliez vraiment créer un objet.