JavaScript ha uno scope lessicale che significa che le variabili non locali a cui si accede da una funzione vengono risolte in variabili presenti nello scope dei genitori di quella funzione quando è stata definita. Questo è in contrasto con lo scope dinamico in cui le variabili non locali accessibili all'interno di una funzione vengono risolte in variabili presenti nell'ambito di chiamata di quella funzione quando viene chiamato.È possibile raggiungere lo scoping dinamico in JavaScript senza ricorrere a eval?
x=1
function g() { echo $x ; x=2 ; }
function f() { local x=3 ; g ; }
f # does this print 1, or 3?
echo $x # does this print 1, or 2?
Le stampe di cui sopra del programma 1 e poi 2 in una lingua con scope lessicale, e la stampa 3 e poi 1 in una lingua ambito in modo dinamico. Dal momento che JavaScript è lessicalmente ambito verrà stampata 1 e poi 2 come illustrato di seguito:
var print = x => console.log(x);
var x = 1;
function g() {
print(x);
x = 2;
}
function f() {
var x = 3;
g();
}
f(); // prints 1
print(x); // prints 2
Anche se JavaScript non supporta scoping dinamico possiamo attuarlo utilizzando eval
come segue:
var print = x => console.log(x);
var x = 1;
function g() {
print(x);
x = 2;
}
function f() {
// create a new local copy of `g` bound to the current scope
// explicitly assign it to a variable since functions can be unnamed
// place this code in the beginning of the function - manual hoisting
var g_ = eval("(" + String(g) + ")");
var x = 3;
g_();
}
f(); // prints 3
print(x); // prints 1
Vorrei sapere se esiste un altro modo possibile per ottenere lo stesso risultato senza ricorrere a eval
.
Edit: Questo è quello che sto cercando di attuare senza utilizzare eval
:
var print = x => console.log(x);
function Class(clazz) {
return function() {
var constructor;
var Constructor = eval("(" + String(clazz) + ")");
Constructor.apply(this, arguments);
constructor.apply(this, arguments);
};
}
var Rectangle = new Class(function() {
var width, height;
constructor = function (w, h) {
width = w;
height = h;
};
this.area = function() {
return width * height;
};
});
var rectangle = new Rectangle(2, 3);
print(rectangle.area());
So che non è un buon esempio, ma l'idea generale è di usare scoping dinamico per creare chiusure. Penso che questo modello abbia un grande potenziale.
Ben scritta, domanda interessante. Sebbene chieda una risposta obiettiva, a meno che qualcuno non mostri come può essere fatto, sospetto che provocherà molto dibattito e risposte soggettive sul perché non può o non dovrebbe essere fatto. Cosa ti ha portato a questa domanda? –
@ChrisWesseling - Ho aggiornato la mia domanda per mostrare cosa mi ha fatto postare. Il programma di cui sopra è perfettamente valido e funziona su tutte le piattaforme. Credo che abbia molte potenzialità per creare modelli di classe e molte altre cose. Spetta al pubblico usarlo saggiamente. Forse uno degli unici validi motivi per usare 'eval'. –
Il motivo per cui voglio utilizzare lo scoping dinamico è che posso iniettare variabili private nell'ambito di una funzione. Per esempio, nel mio programma precedente posso anche passare una variabile chiamata 'uber' che punta al genitore della classe data. Questa variabile dovrebbe essere accessibile allo scope di classe ma non dovrebbe essere accessibile al pubblico. Quindi non posso semplicemente impostarlo sull'istanza della classe e chiamarlo un giorno. Quindi la soluzione alternativa alla rotonda. –