Newsgroup: it.comp.lang.javascript
Titolo: nome variabile uguale nella funzione annidata

ho creato questa classe:
 
function test(){
	var x=1;
 
	this.accesso = function(){
		var x=2;
		alert(x);
	}
}
 
quindi creo un'istanza e richiamo la funzione 'accesso':
 
	var c = new test();
	c.accesso();
 
Viene quindi visualizzato "2", ossia il valore della variabile 'x', 
dichiarata all'interno della funzione 'accesso'.
Ma se volessi accedere alla variabile (omonima) dichiarata all'interno 
della funzione (classe) "test"?
In pratica devo andare al livello superiore; ho provato quindi a sostituire
 
		alert(x);
 
con qualcosa tipo
 
		alert(parent.x);
 
ma naturalmente, come immaginavo non funge, non � il metodo corretto...
Suggerimenti?

 Suggerimenti?
 
Cambia nome alle variabili. Oppure non usare variabili nel costruttore,
ma propriet�.
 
Inoltre considera che il tuo codice crea un metodo nuovo per ogni
oggetto creato dal costruttore:
 
    // Attento alla naming convention, i costruttori hanno la prima
    // lettera sempre maiuscola
    function Test(){
        this.accesso = function(){}
    }
 
    var a = new Test();
    var b = new Test();
 
    alert(a.accesso === b.accesso); // false
 
Mentre:
 
    function Test(){
    }
 
    Test.prototype.accesso = function() {}
 
    var a = new Test();
    var b = new Test();
 
    alert(a.accesso === b.accesso); // true
 
Ovviamente nel secondo modo non hai accesso alle variabili dichiarate
nello scopo del costruttore, ma essendo JS un linguaggio dinamico
solitamente non ne hai bisogno (un po' come Python); a meno che tu non
stia lavorando con due livelli di privilegi differenti, allora la
sicurezza � fondamentale (esempio, il tuo oggetto gira come codice per
Add-on di un browser e quindi ha privilegi superiori a quello di una
pagina web, e non devi far accedere a certe propriet� "dal basso").
 
Last but not least, con il tuo codice originale crei una closure. Le
closure sono un potente mezzo di JavaScript (e non solo), ma devono
essere comprese e soprattutto non abusate, anche perch� altrimenti
portano a bug difficilmente scovabili da chi non � abituato e a memory
leak (soprattutto con riferimenti circolari e al DOM):
 
http://jibbering.com/faq/notes/closures/
 
 
Hope it helps.
 


 
con questo esempio (che vale pi� di ogni spiegazione) finalmente ho 
capito appieno il concetto

 pluto, paperino? ;)
 
E` a tutti gli effetti una funzione, che in javascript e` anche un 
oggetto, ma senza classe. :)
 
Bye.

 capito appieno il concetto
 
Ottimo. :)
 

      Test.prototype.accesso = function() {}
 
attenzione, per� in questo modo definisco un "metodo" pubblico (non 
privato).
Se volessi quindi rendere la funzione accessibile solo dall'interno 
dell'oggetto (non uso il termine "classe" altrimenti mi linciate) 
tramite una funzione "pubblica"?
 
L'unica cosa che mi � venuta in mente � di mettere la funzione "privata" 
all'interno dell'oggetto (all'interno del costruttore):
 
function Costruttore() {
	function privata(){
		alert('privata');
	}
}
 
//definisco quindi la funzione pubblica
Costruttore.prototype.pubblica = function() {
	privata();
}
 
var a = new Costruttore();
a.pubblica();
 
Ed ecco spuntare l'errore: privata is not defined!!!!!!!
 
L'unico modo � mettere anche la funzione "pubblica" all'interno 
dell'oggetto:
 
function Costruttore() {
	function privata(){
		alert('privata');
	}
 
	this.pubblica = function() {
		privata();
	}
}
 
Ma, come ha gi� detto "qualcuno", verrebbe creato un metodo nuovo per 
ogni oggetto creato dal costruttore...

 ogni oggetto creato dal costruttore...
 
Esattamente. Non esiste il concetto di pubblico o privato in JS, tutto �
"pubblico". Puoi simulare la cosa, ma generalmente chi lo fa � solo per
abitudini precedenti, e non per reale necessit� (vedasi Python).
 
Se non esiste una reale necessit� di sicurezza, io opterei per una
classica nomenclatura per differenziare variabili che, eventualmente non
dovrebbero essere usate o che comunque rischiano di cambiare (cos�
l'eventuale developer che ne fa uso, lo sa). In JavaScript di solito si
usa l'underscore come prefisso del nome del metodo o propriet�.
 
Come alternativa suggerirei l'uso di moduli CommonJS (o CommonJS-like,
vedasi `requireJS` che mi pare ti sia gi� stato consigliato), dove puoi
definire in stile di programmazione funzionale i metodi generici che
tieni "privati", e cio� non esponi tramite `exports`, che poi richiami
nei metodi "pubblici", cio� quelli esposti. Rimane sempre il fatto che
non puoi fare lo stesso con le propriet� (a meno, appunto, che tu non
usi le WeakMap, ma non tutti i browser ce l'hanno, quindi nel caso
dovresti fare un po' di accrocchi che, onestamente, non mi sento di
consigliarti), per le quali continuo a suggerirti la nomenclatura
classica di cui sopra, almeno per il momento.
 
Per darti del codice concreto (attenzione, richiede requireJS):
 
    define("my-module", function(require, exports, module) {
 
      function aPrivateMethod(self, value) {
        // do something
      }
 
      function MyObject() {
        // constructor
      }
 
      MyObject.prototype.aMethod = function (value) {
        return aPrivateMethod(this, value);
      }
 
      exports.MyObject = MyObject;
    });
 
    require(["my-module"], function(myModule) {
      var a = new myModule.MyObject();
      var b = new myModule.MyObject();
 
      alert(a.aMethod === b.aMethod); // true
    })
 
Volendo potresti anche ottenere lo stesso risultato senza requireJS, il
vantaggio � che requireJS tiene traccia delle dipendenze, e carica tutto
in modo asincrono se hai pi� files (vedasi la documentazione per questo).

 Cito:
 
hai ragione, e sei sempre molto esauriente con le tue spiegazioni.
Il problema � che per molto tempo ho usato solo certi tipi di linguaggi, 
ed ancora non sono riuscito ad entrare appieno nella logica del "dinamico".