Frage

der folgende JavaScript-Schnipsel in einem Umfang Gegeben:

var x = 10;

function sayx() {
  alert(x);
}

sayx();

Sie würden natürlich erwarten, dass ein Meldungsfeld Drucken ‚10‘, könnte man mehr Funktions Verschachtelung tun zu interagieren, wie ‚x‘ wird bestimmt, denn wenn die Lösung, welche x ist die Umgebung, den Umfangs Kette geht auf.

Sie können sogar ein Niveau von ‚Neuübersetzung‘ mit eval tun, um neue Bereiche zur Laufzeit zu injizieren .. zum Beispiel:

var x = 10;

function sayx() {
  alert(x);
}

function wrap(f) {
  return eval('(function() { var x = 20;(' + f + ')(); })');
}

wrap(sayx)();

Das funktioniert, weil die Funktion seiner toString Funktion aufgerufen hat, die die ‚Original‘ Quelle zurückkehren wird .. also im Wesentlichen schaffen wir eine gewickelte Version der Funktion, die einen neuen Bereich hat, die x überschreibt .. das Ergebnis wird eine Warnung sein Box, der Druck '20' und nicht '10'.

jedoch auf der Oberfläche erscheinen könnte dies zu arbeiten, aber der Umfang Kette ist gebrochen, in der Kette das nächste Element ist nicht mehr die gleiche, weil die ‚f‘ Funktion nun an einem anderen Ort definiert ist .. noch schlimmer ist, dass der Umfang Kette es viele Verweise geerbt hat enthalten könnte, dass der anrufende Funktion Zugang zu nicht haben sollte.

So gibt es einen mehr unterstützt, praktikable Weg, um einen Umfang Artikel zu injizieren? so etwas wie:

function withScope(f, scope) { ??? }

---

var x = 10, y = 10;

function dothemath() {
  alert(x + y);
}

var haxthemath = withScope(dothemath, { x: 9000 });
haxthemath(); // 9010 not 20

Ich vermute, die Antwort ist ‚Nein‘, einige argumentieren, kann es ‚Sicherheit‘ Probleme mit einem solchen Umfang Injektion, aber wenn man bedenkt man den Trick trotzdem tun kann (wenn auch stark gebrochen) Ich glaube nicht, es ist ..

Die Vorteile hierfür wäre, dass Sie Ihre eigene Pseudo-Variablen im Wesentlichen fälschen.

Vielen Dank im Voraus.


Bearbeiten, klären nur die ein wenig, stelle ich mir zu ‚withScope‘ wollte eine Funktion, die den Geltungsbereich Kette hatte:

Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }

Ich möchte in der Lage sein, eine Funktion zurück zu bekommen, die effektiv die gleiche Kette hatte + einen Bereich bietet mir .. also:

withScope(somefunc, { foo: 'bar' })

würde ich

Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }
Ext scope - { foo = 'bar' }

Alle vor stehenden Variablen gefunden werden würden, weil mein erweiterten Anwendungsbereich sagt nichts über sie.

War es hilfreich?

Lösung

Wenn Sie mit dem Umfang an die lokalen Variablen in der Funktion und / oder die Schließung sich beziehen, ich denke, die Antwort ist nein.

Sie können den Umfang des this Schlüsselwort ändern, indem Sie mit functionName.call (Umfang, arg1, ...) oder functionName.apply (scope [arg1, ...]); Dies zusammen mit Prototypen verwendet werden könnte, um ähnliche Ketten zu erstellen, wie Sie beschreiben - wenn etwas nicht in dem Objekt eigenen Eigenschaften gefunden, es in seinem Prototyp nachgeschlagen. Wenn die Eigenschaft nicht vorhanden ist, wird der nächste Prototyp in der Kette verwendet und so weiter.

Andere Tipps

die Antwort, die ich glaube, Sie suchen die eingebauten „mit“ Anweisung für wird.

Allerdings würde ich nicht empfehlen, es zu benutzen, da es veraltet ist, und wird sehr wahrscheinlich existieren nicht in ECMAScript 6

Die einzige andere Art und Weise ich glaube, Sie diese Art der Sache tun könnten, ist aus dem Innern der Host-Anwendung selbst, die JavaScript-Umgebung von außen zu manipulieren. Oder, wenn Sie Nashorn verwenden, können Sie tatsächlich tun, dass von innen JavaScript aktivieren, weil die Verbindung zwischen Java-APIs und Javascript in rhino nur, dass nahtlos ist. Wenn Steve Yegge zuerst, dass darauf hingewiesen, blies es meinen Kopf. Manipulieren Sie Javascript außerhalb von JavaScript, aber von innen Javascript! Es ist genial!

Wenn Sie in einer Browser-Umgebung stecken, vielleicht können Sie ein JavaScript-Interpreter in Javascript geschrieben verwenden, wie Narzisse.

Sie Javascript Vielleicht in toString Methode zur integrierten Funktionen verwenden?

function withScope(f, scope) {
    var toExec = "";
    for (var prop in scope) {
        toExec += "var " + prop + " = scope['" + prop + "'];"
    }
    toExec += "f = (" + f.toString() + ")";
    eval(toExec);
    return f;
}
var x = 10;
var f = function() {
    console.log(x);
};
withScope(f, {x: 20})();

Das scheint wie eine schlechte Idee aber ...

Sie, wenn mit Rahmen spielen, um möchten Sie möglicherweise die let Anweisung zur Verfügung gestellt in Javascript 1.7 genießen. Neue Versionen von Firefox Unterstützung let .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top