2012-05-23 20 views
13

ho questa classe:javascript accesso funzione privata variabile pubblica

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

e lo chiamo:

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

non si suppone che il secondo avviso popup "huhu"? func2 è privato, non può accedere alla variabile pubblica var1?

se una funzione privata non può accedere a una variabile pubblica, come posso farlo?

Grazie in anticipo!

+2

Inoltre, non esiste una cosa come "privata" qui. – Alexander

+0

Questo 'obj.func1()' dovrebbe essere presumibilmente 'myobj.func1()' – forsvarir

+0

@forsvarir si dovrebbe - l'ho risolto per lui. – Alnitak

risposta

17

è necessario fornire un contesto per la chiamata a func2:

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

Senza il contesto della chiamata utilizzerà l'oggetto globale (cioè window) - si dovrebbe vedere quando si esegue il codice corrente che window.var1 è essere creato tra i due avvisi.

+0

se faccio quello che hai suggerito dice che func2() non è una funzione – MIrrorMirror

+0

@MIrrorMirror ah, umm, sì - aspetta! – Alnitak

+0

@Alnitak Si prega di leggere il suo codice, func2 non è una funzione pubblica. – 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"; 
    } 
} 

E non c'è altro modo per risolvere questo problema, controllare le altre risposte :)

+0

Il downvoter dovrebbe dare la tua motivazione. – xdazz

+0

@Alnitak Ma questo non sarà un problema, 'obj' è un parametro. – xdazz

12

Le funzioni non sono legate a istanze, quindi il vostro invocazione func2 finisce come invocazione senza this indicando l'istanza previsto .

È possibile correggere l'invocazione per includere il contesto:

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

Oppure si può mantenere una variabile con il riferimento all'oggetto desiderato in giro:

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

grazie! questo mi ha aiutato molto –

+0

puoi fornire ulteriori approfondimenti su questo argomento, perché voglio sapere quale è la migliore pratica e perché – InsOp

+1

@InsOp suggerisco di leggere l'aiuto MDN sulla parola chiave "this": https: //developer.mozilla.org/it-it/docs/Web/JavaScript/Reference/Operators/this – Lucero

2

Un'altra opzione è quella di utilizzare 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); 
} 

Si noti che il supporto del browser per questo non è perfetto.

+0

Perché usare 'that' _and_' .bind() 'allo stesso tempo? – Alnitak

+0

@Alnitak: copia e incollatura scadenti – Eric

2

Non esiste una cosa privata in JS, ma è possibile giocare con gli ambiti utilizzando lo closures.

Diciamo ad esempio che nel tuo esempio non è necessario esporre var1 come proprietà pubblica. Si potrebbe facilmente riscrivere il codice come il seguente:

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

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

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

Poiché sia ​​func1 e func2 condivide la stessa portata - sono definiti nella stessa funzione, ctest - possono accedere alle stesse variabili. Naturalmente in tal caso non si dispone di var1 esposto, quindi: myobj.var1 sarà undefined.

Se si desidera var1 per essere esposti come proprietà, allora quello che ti serve è bindfunc2 all'istanza oggetto creato nel costruttore:

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

Altrimenti func2 avrà un oggetto contesto diverso (this). Se il browser non supporta bind e non si desidera utilizzare uno spessore (come mostrato nel link qui sotto), è possibile usufruire delle chiusure ancora:

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 è meno elegante.

Problemi correlati