JavaScript für ungeduldige Programmierer (ES2022-Ausgabe)
Bitte unterstützen Sie dieses Buch: kaufen Sie es oder spenden Sie
(Werbung, bitte nicht blockieren.)

26 Dynamische Codeauswertung: eval(), new Function() (fortgeschritten)



In diesem Kapitel befassen wir uns mit zwei Möglichkeiten der dynamischen Codeauswertung: eval() und new Function().

26.1 eval()

Gegeben eine Zeichenkette str mit JavaScript-Code, wertet eval(str) diesen Code aus und gibt das Ergebnis zurück.

> eval('2 ** 4')
16

Es gibt zwei Möglichkeiten, eval() aufzurufen:

„Nicht über einen Funktionsaufruf“ bedeutet „alles, was anders aussieht als eval(···)“.

Der folgende Code veranschaulicht den Unterschied.

globalThis.myVariable = 'global';
function func() {
  const myVariable = 'local';
  
  // Direct eval
  assert.equal(eval('myVariable'), 'local');
  
  // Indirect eval
  assert.equal(eval.call(undefined, 'myVariable'), 'global');
}

Die Auswertung von Code im globalen Kontext ist sicherer, da der Code Zugriff auf weniger Interna hat.

26.2 new Function()

new Function() erstellt ein Funktions-Objekt und wird wie folgt aufgerufen:

const func = new Function('«param_1»', ···, '«param_n»', '«func_body»');

Die vorherige Anweisung ist äquivalent zur nächsten Anweisung. Beachten Sie, dass «param_1» usw. nicht mehr innerhalb von Zeichenkettenliteralen stehen.

const func = function («param_1», ···, «param_n») {
  «func_body»
};

Im nächsten Beispiel erstellen wir dieselbe Funktion zweimal, zuerst über new Function(), dann über einen Funktionsausdruck.

const times1 = new Function('a', 'b', 'return a * b');
const times2 = function (a, b) { return a * b };

  new Function() erstellt Funktionen im non-strict mode

Standardmäßig sind Funktionen, die über new Function() erstellt werden, sloppy. Wenn wir möchten, dass der Funktionskörper im strict mode ausgeführt wird, müssen wir ihn manuell aktivieren.

26.3 Empfehlungen

Vermeiden Sie die dynamische Auswertung von Code so weit wie möglich.

Sehr oft ist JavaScript dynamisch genug, sodass Sie eval() oder Ähnliches nicht benötigen. Im folgenden Beispiel kann das, was wir mit eval() tun (Zeile A), genauso gut ohne es erreicht werden (Zeile B).

const obj = {a: 1, b: 2};
const propKey = 'b';

assert.equal(eval('obj.' + propKey), 2); // (A)
assert.equal(obj[propKey], 2); // (B)

Wenn Sie Code dynamisch auswerten müssen: