Ist es möglich, dynamisches Scoping in JavaScript zu erreichen, ohne auf eval zurückzugreifen?

JavaScript hat einen lexikalischen Gültigkeitsbereich, was bedeutet, dass nicht-lokale Variablen, auf die innerhalb einer Funktion zugegriffen wird, in Variablen aufgelöst werden, die zum Zeitpunkt der Definition im Gültigkeitsbereich dieser Funktion der Eltern vorhanden waren. Dies steht im Gegensatz zu dynamischem Scoping, bei dem nicht-lokale Variablen, auf die von einer Funktion aus zugegriffen wird, in Variablen aufgelöst werden, die beim Aufruf im aufrufenden Bereich dieser Funktion vorhanden sind.

<code>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?
</code>

Das obige Programm gibt 1 und dann 2 in einer Sprache mit lexikalischem Gültigkeitsbereich und 3 und dann 1 in einer Sprache mit dynamischem Gültigkeitsbereich aus. Da JavaScript lexikalisch ist, wird 1 und dann 2 ausgegeben, wie unten gezeigt:

<code>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</code>

Obwohl JavaScript dynamisches Scoping nicht unterstützt, können wir es mit implementiereneval wie folgt:

<code>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</code>

Ich würde gerne wissen, ob es einen anderen Weg gibt, um das gleiche Ergebnis zu erzielen, ohne darauf zurückzugreifeneval.

Bearbeiten: Dies ist, was ich versuche zu implementieren, ohne zu verwendeneval:

<code>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());</code>

Ich weiß, dass es kein sehr gutes Beispiel ist, aber die allgemeine Idee ist, dynamisches Scoping zu verwenden, um Abschlüsse zu erstellen. Ich denke, dieses Muster hat viel Potenzial.

Antworten auf die Frage(7)

Ihre Antwort auf die Frage