2009-02-28 9 views
18

Se si desidera utilizzare le funzioni globali e variabili in modo dinamico è possibile utilizzare:Come posso accedere dinamicamente all'ambito locale in javascript?

window[functionName](window[varName]); 

E 'possibile fare la stessa cosa per le variabili in ambito locale?

Questo codice funziona correttamente ma attualmente utilizza eval e sto cercando di pensare a come altro farlo.

var test = function(){ 
    //this = window 
    var a, b, c; //private variables 

    var prop = function(name, def){ 
     //this = window 
     eval(name+ ' = ' + (def.toSource() || undefined) + ';');  

     return function(value){ 
      //this = test object 
      if (!value) { 
       return eval('(' + name + ')'); 
      } 
      eval(name + ' = value;') 
      return this; 
     }; 

    }; 

    return { 
     a:prop('a', 1), 
     b:prop('b', 2), 
     c:prop('c', 3), 
     d:function(){ 
      //to show that they are accessible via to methods 
      return [a,b,c]; 
     } 
    }; 
}(); 

>>>test 
Object 
>>>test.prop 
undefined 
>>>test.a 
function() 
>>>test.a() 
1 //returns the default 
>>>test.a(123) 
Object //returns the object 
>>>test.a() 
123 //returns the changed private variable 
>>>test.d() 
[123,2,3] 
+1

Ottengo il motivo per cui ero confuso ora, è perché stai nominando le variabili abc così come i nomi per il ritorno. Dovresti cambiare quei nomi, è questo che mi stava confondendo. Ad ogni modo, le risposte migliori della mia si sono rivelate, quindi mi limiterò a rimandare a crescentfresh a questo punto. –

+0

@ Gothdo La domanda a cui ti colleghi sta chiedendo qualcosa di diverso. Le variabili a cui sta tentando di accedere sono variabili globali. La risposta accettata utilizza anche variabili globali. La domanda collegata dovrebbe essere cambiata. – Annan

risposta

6

No, come crescentfresh detto. Di seguito trovi un esempio di come implementare senza eval, ma con un oggetto privato interno.

var test = function() { 
    var prv={ }; 
    function prop(name, def) { 
    prv[name] = def; 
    return function(value) { 
     // if (!value) is true for 'undefined', 'null', '0', NaN, '' (empty string) and false. 
     // I assume you wanted undefined. If you also want null add: || value===null 
     // Another way is to check arguments.length to get how many parameters was 
     // given to this function when it was called. 
     if (typeof value === "undefined"){ 
     //check if hasOwnProperty so you don't unexpected results from 
     //the objects prototype. 
     return Object.prototype.hasOwnProperty.call(prv,name) ? prv[name] : undefined; 
     } 
     prv[name]=value; 
     return this; 
    } 
    }; 

    return pub = { 
    a:prop('a', 1), 
    b:prop('b', 2), 
    c:prop('c', 3), 
    d:function(){ 
     //to show that they are accessible via two methods 
     //This is a case where 'with' could be used since it only reads from the object. 
     return [prv.a,prv.b,prv.c]; 
    } 
    }; 
}(); 
+0

Che dire dell'enumerazione delle variabili locali nella funzione stessa? In altre parole, come eval, ma quando non sai cosa sono i locali ... – Michael

+0

@ Michael Mi dispiace, ma non capisco cosa intendi. Potresti fare un esempio? O forse scrivi anche la tua risposta? – some

+0

non ho una risposta, e tutto ciò che ho letto sembra suggerire che è impossibile ... le variabili globali in un browser possono essere enumerate con qualcosa come 'for (i in window)'; sarebbe bello se ciò fosse possibile per i locali in una funzione. – Michael

2

Speriamo che io non sono di semplificare eccessivamente, ma che dire qualcosa di semplice come usare un oggetto?

var test = { 
    getValue : function(localName){ 
     return this[localName]; 
    }, 
    setValue : function(localName, value){ 
     return this[localName] = value; 
    } 
}; 

>>> test.a = 123 
>>> test.getValue('a') 
123 
>>> test.a 
123 

>>> test.setValue('b', 999) 
999 
>>> test.b 
999 
+0

Se stai per accedere direttamente alle variabili locali dell'oggetto, qual è il punto di definizione di un getter o setter? –

+0

Non ce n'è uno. Ho appena aggiunto che l'uso sarebbe identico all'esempio di Annan. Sono d'accordo, sarebbe completamente stupido nella pratica. –

+0

Il motivo per il codice è quello di emulare il modo in cui i getter e i setter funzionano in modo cross browser. Pertanto il mio codice originale era errato (ora risolto) poiché le variabili prop() create non erano disponibili per il resto dell'oggetto. La tua strada consente l'accesso diretto e la manipolazione delle proprietà. – Annan

7

Per rispondere alla tua domanda, no, non c'è modo di fare ricerca variabile dinamica in un ambito locale senza utilizzare eval().

L'alternativa migliore è rendere il tuo "ambito" solo un oggetto regolare [letterale] (ovvero, "{}") e incollare i tuoi dati lì.