with
Veraltet: Diese Funktion wird nicht mehr empfohlen. Obwohl einige Browser sie möglicherweise noch unterstützen, könnte sie bereits aus den relevanten Webstandards entfernt worden sein, in Kürze entfernt werden oder nur noch aus Kompatibilitätsgründen bestehen. Vermeiden Sie die Verwendung und aktualisieren Sie vorhandenen Code, falls möglich; siehe die Kompatibilitätstabelle am Ende dieser Seite, um Ihre Entscheidung zu unterstützen. Beachten Sie, dass diese Funktion jederzeit aufhören könnte zu funktionieren.
Hinweis:
Die Verwendung des with
-Statements wird nicht empfohlen, da es die Quelle verwirrender Fehler und Kompatibilitätsprobleme sein kann, Optimierung unmöglich macht und im strict mode verboten ist. Die empfohlene Alternative ist, das Objekt, dessen Eigenschaften Sie zugreifen möchten, einer temporären Variablen zuzuweisen.
Das with
-Statement erweitert die Scope-Kette für ein Statement.
Syntax
with (expression)
statement
expression
-
Fügt der Scope-Kette, die beim Auswerten des Statements verwendet wird, den angegebenen Ausdruck hinzu. Die Klammern um den Ausdruck sind erforderlich.
statement
-
Beliebiges Statement. Um mehrere Statements auszuführen, verwenden Sie ein Block-Statement (
{ ... }
), um diese Statements zu gruppieren.
Beschreibung
Es gibt zwei Arten von Bezeichnern: einen qualifizierten Bezeichner und einen unqualifizierten Bezeichner. Ein unqualifizierter Bezeichner ist einer, der nicht angibt, woher er stammt.
foo; // unqualified identifier
foo.bar; // bar is a qualified identifier
Normalerweise wird ein unqualifizierter Bezeichner aufgelöst, indem die Scope-Kette nach einer Variable mit diesem Namen durchsucht wird, während ein qualifizierter Bezeichner durch die Suche in der Prototyp-Kette eines Objekts nach einer Eigenschaft mit diesem Namen aufgelöst wird.
const foo = { bar: 1 };
console.log(foo.bar);
// foo is found in the scope chain as a variable;
// bar is found in foo as a property
Eine Ausnahme bildet das globale Objekt, das sich an der Spitze der Scope-Kette befindet und dessen Eigenschaften automatisch zu globalen Variablen werden, auf die ohne Qualifier verwiesen werden kann.
console.log(globalThis.Math === Math); // true
Das with
-Statement fügt das angegebene Objekt an den Anfang dieser Scope-Kette während der Auswertung seines Statement-Körpers hinzu. Jeder unqualifizierte Name wird zuerst innerhalb des Objekts (durch einen in
-Check) durchsucht, bevor in der oberen Scope-Kette gesucht wird.
Beachten Sie, dass, wenn der unqualifizierte Verweis auf eine Methode des Objekts verweist, die Methode mit dem Objekt als this
-Wert aufgerufen wird.
with ([1, 2, 3]) {
console.log(toString()); // 1,2,3
}
Das Objekt kann eine [Symbol.unscopables]
-Eigenschaft haben, die eine Liste von Eigenschaften definiert, die nicht zur Scope-Kette hinzugefügt werden sollen (aus Gründen der Rückwärtskompatibilität). Weitere Informationen finden Sie in der Dokumentation zu Symbol.unscopables
.
Die Gründe, ein with
-Statement zu verwenden, sind unter anderem das Einsparen einer temporären Variable und die Reduzierung der Dateigröße, indem ein langes Objekt-Referenzieren vermieden wird. Es gibt jedoch weit mehr Gründe, warum with
-Statements nicht wünschenswert sind:
-
Leistung: Das
with
-Statement zwingt das angegebene Objekt, zuerst für alle Namensauflösungen durchsucht zu werden. Daher werden alle Bezeichner, die keine Mitglieder des angegebenen Objekts sind, langsamer in einemwith
-Block gefunden. Darüber hinaus kann der Optimierer keine Annahmen darüber treffen, worauf sich jeder unqualifizierte Bezeichner bezieht, sodass er jedes Mal, wenn der Bezeichner verwendet wird, die gleiche Eigenschaftssuche wiederholen muss. -
Lesbarkeit: Das
with
-Statement macht es für einen menschlichen Leser oder JavaScript-Compiler schwer zu entscheiden, ob ein unqualifizierter Name entlang der Scope-Kette gefunden wird und wenn ja, in welchem Objekt. Zum Beispiel:jsfunction f(x, o) { with (o) { console.log(x); } }
Wenn Sie nur die Definition von
f
betrachten, ist es unmöglich zu sagen, worauf sich dasx
imwith
-Körper bezieht. Erst wennf
aufgerufen wird, kannx
also.x
oder das erste formale Parameter vonf
bestimmt werden. Wenn Sie vergessen,x
im Objekt zu definieren, das Sie als zweiten Parameter übergeben, erhalten Sie keinen Fehler – stattdessen bekommen Sie einfach unerwartete Ergebnisse. Es ist auch unklar, was die tatsächliche Absicht eines solchen Codes wäre. -
Zukunftskompatibilität: Code, der
with
verwendet, ist möglicherweise nicht zukunftskompatibel, insbesondere wenn er mit etwas anderem als einem einfachen Objekt verwendet wird, das in Zukunft möglicherweise mehr Eigenschaften erhält. Betrachten Sie dieses Beispiel:jsfunction f(foo, values) { with (foo) { console.log(values); } }
Wenn Sie
f([1, 2, 3], obj)
in einer ECMAScript 5-Umgebung aufrufen, wird dervalues
-Verweis innerhalb deswith
-Statements zuobj
aufgelöst. Allerdings führt ECMAScript 2015 einevalues
-Eigenschaft imArray.prototype
ein (sodass diese auf jedem Array verfügbar ist). Nach dem Upgrade der Umgebung wird dervalues
-Verweis innerhalb deswith
-Statements stattdessen zu[1, 2, 3].values
aufgelöst und wird wahrscheinlich Bugs verursachen.In diesem speziellen Beispiel wird
values
als nicht-inklusiv durchArray.prototype[Symbol.unscopables]
definiert, sodass es immer noch korrekt auf denvalues
-Parameter aufgelöst wird. Wäre es nicht als nicht-inklusiv definiert, könnte man sehen, wie dies ein schwieriges Problem zu debuggen wäre.
Beispiele
Verwendung des with-Statements
Das folgende with
-Statement gibt an, dass das Math
-Objekt das Standardobjekt ist. Die auf das with
-Statement folgenden Anweisungen beziehen sich auf die PI
-Eigenschaft sowie die cos
- und sin
-Methoden, ohne ein Objekt anzugeben. JavaScript nimmt an, dass die Referenzen auf das Math
-Objekt bezogen sind.
let a, x, y;
const r = 10;
with (Math) {
a = PI * r * r;
x = r * cos(PI);
y = r * sin(PI / 2);
}
Vermeidung des with-Statements durch Destrukturierung von Eigenschaften in den aktuellen Scope
Sie können die Verwendung von with
im Allgemeinen durch Destrukturierung von Eigenschaften vermeiden. Hier erstellen wir einen zusätzlichen Block, um das Verhalten von with
, das einen zusätzlichen Scope schafft, nachzuahmen – aber in der tatsächlichen Verwendung kann dieser Block normalerweise weggelassen werden.
let a, x, y;
const r = 10;
{
const { PI, cos, sin } = Math;
a = PI * r * r;
x = r * cos(PI);
y = r * sin(PI / 2);
}
Vermeidung des with-Statements durch Verwendung einer IIFE
Wenn Sie einen Ausdruck erstellen, der einen langen Referenznamen mehrmals wiederverwenden muss, und Ihr Ziel darin besteht, diesen langen Namen in Ihrem Ausdruck zu eliminieren, können Sie den Ausdruck in eine IIFE einwickeln und den langen Namen als Argument übergeben.
const objectHavingAnEspeciallyLengthyName = { foo: true, bar: false };
if (((o) => o.foo && !o.bar)(objectHavingAnEspeciallyLengthyName)) {
// This branch runs.
}
Erstellen dynamischer Namensräume durch Verwendung des with-Statements und eines Proxys
with
wird jede Variablen-Suche in eine Eigenschafts-Suche umwandeln, während Proxies das Abfangen jeder Eigenschafts-Suche ermöglichen. Sie können einen dynamischen Namensraum erstellen, indem Sie sie kombinieren.
const namespace = new Proxy(
{},
{
has(target, key) {
// Avoid trapping global properties like `console`
if (key in globalThis) {
return false;
}
// Trap all property lookups
return true;
},
get(target, key) {
return key;
},
},
);
with (namespace) {
console.log(a, b, c); // "a" "b" "c"
}
Spezifikationen
Specification |
---|
ECMAScript® 2025 Language Specification # sec-with-statement |
Browser-Kompatibilität
BCD tables only load in the browser