2009-03-23 7 views
2

La portée variable dans JS me déroute complètement. Dans le code suivant, si j'utilise la méthode publique setClient pour définir un clientID, je peux alors accéder à la valeur depuis la méthode track en utilisant la méthode getClient. Je ne peux cependant pas accéder à la valeur de la version privée du membre de cette façon (ou de tout autre membre privé) .. J'avais supposé que var _this = cela créerait une sorte de fermeture permettant l'accès à la portée de la fonction Container.Portée variable JS

Et maintenant je suis confus. Je réalise que c'est probablement très simple, alors j'ai pensé que je demanderais ici. Où sur terre avez-vous saisi la mauvaise extrémité du bâton?

function Container() 
{ 
    // private members 
    var version = '0.1'; 
    var CID = false; 
    var _this = this; 

    // public members 
    this.getVersion = function() { return _this.version; } 
    this.getClient = function() { return _this.CID; } 
    this.setClient = function(CID) { _this.CID = CID; } 

    // private methods 
    this.getQS = function() { return _this.version; } 

    // public methods 
    this.track = function() 
    { 
     if (_this.CID) 
     { 
      var date = new Date(); 

      data = 
      { 
       cid: _this.getClient(), 
       sw: screen.width ? screen.width : false, 
       sh: screen.height ? screen.height : false, 
       d: date.getTime() 
      } 

      qs = ''; 

      for (p in data) { qs += p+'~'+data[p]+'-'; } 

      var elHd = document.getElementsByTagName("head")[0];   
      var elScr = document.createElement('script'); 

      elScr.type = 'text/javascript'; 
      elScr.src = 'http://example.org/'+qs+ 
          'version-'+_this.getVersion(); 

      elHd.appendChild(elScr); 
     } 
     else 
     { 
      alert('no client ID'); 
     } 
    } 
} 

Répondre

1

Nettoyez un peu votre constructeur Container. Les variables de version et de CID sont privées et appartiennent à la portée du constructeur du conteneur; vous n'avez donc pas besoin de cette référence de portée, et cela ne fonctionnerait pas du tout. ce. Une référence serait nécessaire pour les propriétés et les méthodes accessibles au public, et extrêmement utile lorsque vous définissez le prototype en dehors de la fonction constructeur, comme indiqué dans le second bloc de code.

function Container() { 
    var version = "0.1", CID = false; 

    this.getVersion = function()  { return version }; 
    this.getClient = function()  { return CID  }; 
    this.setClient = function(value) { CID = value }; 

    this.track = function() { 
    if (CID) { 
     var qs = "", data = { 
     cid: this.getClient(), 
     sw: screen.width ? screen.width: false, 
     sh: screen.height ? screen.height: false, 
     d: (new Date).getTime() 
     }; 
     for (var p in data) qs += p +"~"+ data[p] +"-"; 
     var js = document.createElement("script"); 
     js.type = "text/javascript"; 
     js.src = "http://example.org/"+ qs +"version-"+ this.getVersion(); 
     document.getElementsByTagName("head")[0].appendChild(js); 
    } else { 
     alert("No Client ID"); 
    } 
    }; 
}; 

ce. La référence devient cruciale lorsque vous ajoutez/redéfinissez le prototype après le constructeur.

function Container2() { } 
Container2.prototype = { 
    CID: null, 
    version: "0.1", 
    track: function() { 
    alert(this.version); 
    } 
} 
+0

Merci beaucoup. Je travaillais clairement sous la fausse impression que j'avais besoin de créer une fermeture ou une référence de quelque sorte. Je pense qu'il est de retour pour les livres o'reilly pour moi – jthompson

+0

Pas de problème, il faut un peu pour envelopper votre tête autour d'elle. Et comme mentionné dans un autre post ici, http://www.crockford.com/javascript/private.html est une excellente lecture pour aider à solidifier comment cela fonctionne. –

0

Je ne suis pas sûr je comprends où vous êtes confus (ou pourquoi vous faites les choses de la façon dont vous êtes, donc je peut être méta-confus). Qu'est-ce qui se passe si vous venez:

this.getVersion = function() { return version; } 
0

La variable la version n'est pas un champ de membre de la classe Container. C'est une variable locale qui n'existe que pour la durée du constructeur du conteneur. Vous devez créer ainsi (que vous êtes avec les méthodes):

this.version = "0.1"; 

Vous devriez faire la même chose pour le CID champ. Mieux encore, ajoutez-les à l'objet prototype de votre classe.

0

La réponse est simple à utiliser

this.getVersion = function() { return version; } 

Parce que les fonctions JavaScript sont bouclages la référence à la version, une variable locale, dans la fonction ci-dessus peut être consulté, même après le retour de la fonction. Essayer d'accéder _this.version est une tentative de lire la version membre de l'objet _this. Puisque vous n'avez jamais affecté _this un membre version, il retournera une valeur de indéfini.

En Javascript, vous ne pourrez accéder aux membres qui sont soit ajoutés explicitement à l'objet que vous travaillez avec, ou ajouté au prototype de cet objet, ou le prototype du prototype, etc.

Plus d'info sur l'utilisation de membres privés avec JavaScript peut être trouvé dans un excellent article par Douglas Crockford: Private Members in JavaScript