2012-05-23 7 views
13

j'ai cette classe:javascript accès fonction privée variable publique

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    } 
} 

et appelle:

var myobj = new ctest(); 
    myobj.func1(); 

n'est pas supposé que la seconde alerte PopUp "huhu"? func2 est privé, peut-il accéder à la variable publique var1?

Si une fonction privée ne peut pas accéder à une variable publique, comment puis-je le faire?

Merci d'avance!

+2

Aussi, il n'y a pas une telle chose comme «privé» ici. – Alexander

+0

Ce 'obj.func1()' devrait probablement être 'myobj.func1()' – forsvarir

+0

@forsvarir ouais il devrait - je l'ai corrigé pour lui. – Alnitak

Répondre

17

Vous devez fournir un contexte pour l'appel à func2:

this.func1 = function() { 
    alert(this.var1); 
    func2.call(this); 
    alert(this.var1); 
} 

Sans le contexte de l'appel utilisera l'objet global (c.-à-window) - vous devriez voir lorsque vous exécutez votre code actuel qui window.var1 est se créer entre les deux alertes.

+0

si je fais ce que vous avez suggéré, il dit que func2() n'est pas une fonction – MIrrorMirror

+0

@MIrrorMirror ah, umm, oui - tenir le coup! – Alnitak

+0

@Alnitak S'il vous plaît lire son code, func2 n'est pas une fonction publique. – xdazz

0
function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(this); 
     alert(this.var1); 
    } 
    var func2 = function(obj) { 
     obj.var1 = "huhu"; 
    } 
} 

Et il y a d'autre moyen de résoudre ce problème, vérifiez les autres réponses :)

+0

Le downvoter devrait donner votre raison. – xdazz

+0

@Alnitak Mais ce ne sera pas un problème, 'obj' est un paramètre. – xdazz

12

fonctions ne sont pas liés aux instances, donc votre invocation de func2 finit comme appel sans this pointant vers l'instance prévue .

Vous pouvez fixer l'invocation d'inclure le contexte:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2.call(this); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    } 
} 

Ou vous pouvez garder une variable avec la référence de l'objet recherché autour de:

function ctest() { 
    var that = this; 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     that.var1 = "huhu"; 
    } 
} 
+0

merci! cela m'a beaucoup aidé –

+0

pouvez-vous fournir davantage de lecture sur ce sujet, comme je veux savoir quelle est la meilleure pratique et pourquoi – InsOp

+1

@InsOp Je suggère de lire l'aide de MDN sur le mot-clé "this": https: //developer.mozilla.org/fr-fr/docs/Web/JavaScript/Référence/Opérateurs/this – Lucero

2

Une autre option consiste à utiliser Function.bind:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    }.bind(this); 
} 

Notez que la prise en charge par le navigateur n'est pas parfaite.

+0

Pourquoi utiliser 'that' _and_' .bind() 'en même temps? – Alnitak

+0

@Alnitak: Copie et collage médiocres – Eric

2

Il n'y a rien de privé dans JS, mais vous pouvez jouer avec des étendues en utilisant le closures. Par exemple, disons que dans votre exemple, vous n'avez pas besoin d'exposer var1 comme propriété publique. Vous pouvez facilement réécrire votre code comme suit:

function ctest() { 
    var var1 = "haha"; 

    this.func1 = function() { 
     alert(var1); 
     func2(); 
     alert(var1); 
    } 

    var func2 = function() { 
     var1 = "huhu"; 
    } 
} 

Parce que les deux func1 et func2 partage la même portée - ils sont définis dans la même fonction, ctest - ils peuvent accéder aux mêmes variables. Bien sûr, dans ce cas vous n'avez pas var1 exposé, donc: myobj.var1 sera undefined.

Si vous voulez var1 d'être exposé comme propriété, ce dont vous avez besoin est bindfunc2 à l'instance d'objet créé dans le constructeur:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    }.bind(this); 
} 

Sinon func2 aura un objet contexte différent (this). Si le navigateur ne supporte pas bind et vous ne voulez pas utiliser une cale (comme indiqué dans le lien ci-dessus), vous pouvez profiter des fermetures à nouveau:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var context = this; 
    var func2 = function() { 
     context.var1 = "huhu"; 
    } 
} 

IMVHO est moins élégante.

Questions connexes