Alan Storms Kommentare als Antwort auf meine Antwort bezüglich der with
Aussage brachten mich zum Nachdenken. Ich habe selten einen Grund gefunden, diese spezielle Sprachfunktion zu verwenden, und hatte nie viel darüber nachgedacht, wie sie Probleme verursachen könnte. Jetzt bin ich gespannt, wie ich diese effektiv nutzen with
und gleichzeitig die Fallstricke vermeiden kann.
Wo haben Sie die with
Aussage nützlich gefunden?
with
so dass es so etwas nicht mehr gibt.Antworten:
Mir ist heute eine andere Verwendung eingefallen, daher habe ich das Web aufgeregt durchsucht und eine vorhandene Erwähnung gefunden: Definieren von Variablen innerhalb des Blockbereichs .
Hintergrund
JavaScript legt trotz seiner oberflächlichen Ähnlichkeit mit C und C ++ keine Variablen für den Block fest, in dem sie definiert sind:
Das Deklarieren eines Abschlusses in einer Schleife ist eine häufige Aufgabe, bei der dies zu Fehlern führen kann:
Da die for-Schleife keinen neuen Bereich einführt, wird derselbe
num
- mit dem Wert2
- von allen drei Funktionen gemeinsam genutzt.Ein neuer Anwendungsbereich:
let
undwith
Mit der Einführung der
let
Anweisung in ES6 wird es einfach, bei Bedarf einen neuen Geltungsbereich einzuführen, um diese Probleme zu vermeiden:Oder auch:
Bis ES6 universell verfügbar ist, bleibt diese Verwendung auf die neuesten Browser und Entwickler beschränkt, die bereit sind, Transpiler zu verwenden. Wir können dieses Verhalten jedoch leicht simulieren, indem wir
with
:Die Schleife funktioniert jetzt wie vorgesehen und erstellt drei separate Variablen mit Werten von 0 bis 2. Beachten Sie, dass im Block deklarierte Variablen im Gegensatz zum Verhalten von Blöcken in C ++ keinen Gültigkeitsbereich haben (in C müssen Variablen zu Beginn deklariert werden ein Block, also in gewisser Weise ähnlich). Dieses Verhalten ähnelt einer
let
Blocksyntax, die in früheren Versionen von Mozilla-Browsern eingeführt wurde, an anderer Stelle jedoch nicht weit verbreitet ist.quelle
for (var i = 0; i < 3; ++i) { setTimeout ((function () { var num = i; return function () { alert (num); }; }) (), 10);}
var toString = function () { return "Hello"; }; with ({"test":1}) { console.log(toString()); };
. Im Bereich der with- Anweisung ist toString () eine geerbte Eigenschaft von Object , sodass die explizit definierte Funktion nicht aufgerufen wird. Trotzdem eine gute Antwort :-)Ich habe die with-Anweisung als einfache Form des Bereichsimports verwendet. Angenommen, Sie haben eine Art Markup-Builder. Anstatt zu schreiben:
Sie könnten stattdessen schreiben:
Für diesen Anwendungsfall mache ich keine Zuweisung, daher habe ich nicht das damit verbundene Mehrdeutigkeitsproblem.
quelle
context.bezierCurveTo
hundert Mal hintereinander arbeiten, können Sie sagenvar bc2 = context.bezierCurveTo;
und dannbc2(x,x,etc);
jedes Mal gehen, wenn Sie es aufrufen möchten. Das ist ziemlich schnell und noch weniger ausführlich, währendwith
es sehr langsam ist.Wie meine vorherigen Kommentare gezeigt haben, glaube ich nicht, dass Sie
with
sicher verwenden können, egal wie verlockend es in einer bestimmten Situation sein mag. Da das Problem hier nicht direkt behandelt wird, werde ich es wiederholen. Betrachten Sie den folgenden CodeOhne sorgfältige Untersuchung dieser Funktionsaufrufe kann der Status Ihres Programms nach Ausführung dieses Codes nicht ermittelt werden. Wenn
user.name
bereits festgelegt, wird es jetzt seinBob
. Wenn es nicht festgelegt wurde, wird das Globalname
initialisiert oder in geändert,Bob
und dasuser
Objekt bleibt ohnename
Eigenschaft.Fehler passieren. Wenn Sie mit verwenden, werden Sie dies schließlich tun und die Wahrscheinlichkeit erhöhen, dass Ihr Programm fehlschlägt. Schlimmer noch, Sie können auf Arbeitscode stoßen, der absichtlich oder durch den Autor, der nichts über diese Eigenart des Konstrukts weiß, einen globalen Code in den with-Block setzt. Es ist fast so, als würde man auf einem Schalter durchfallen. Sie haben keine Ahnung, ob der Autor dies beabsichtigt hat, und es gibt keine Möglichkeit zu wissen, ob das "Korrigieren" des Codes eine Regression einführt.
Moderne Programmiersprachen sind voller Funktionen. Einige Funktionen haben sich nach jahrelangem Gebrauch als schlecht herausgestellt und sollten vermieden werden. Javascript
with
ist einer von ihnen.quelle
Ich fand die
with
Aussage in letzter Zeit wirklich unglaublich nützlich. Diese Technik ist mir erst wirklich in den Sinn gekommen, als ich mein aktuelles Projekt gestartet habe - eine in JavaScript geschriebene Befehlszeilenkonsole. Ich habe versucht, die Firebug / WebKit-Konsolen-APIs zu emulieren, bei denen spezielle Befehle in die Konsole eingegeben werden können, die jedoch keine Variablen im globalen Bereich überschreiben. Ich dachte daran, als ich versuchte, ein Problem zu überwinden, das ich in den Kommentaren zu Shog9s ausgezeichneter Antwort erwähnt hatte .Um diesen Effekt zu erzielen, habe ich zwei with-Anweisungen verwendet, um einen Bereich hinter dem globalen Bereich zu "schichten":
Das Tolle an dieser Technik ist, dass sie, abgesehen von den Leistungsnachteilen, nicht die üblichen Befürchtungen der
with
Aussage hat, da wir sowieso im globalen Bereich bewerten - es besteht keine Gefahr, dass Variablen außerhalb unseres Pseudo-Bereichs vorhanden sind geändert.Ich war inspiriert, diese Antwort zu posten, als ich zu meiner Überraschung die gleiche Technik fand, die an anderer Stelle verwendet wurde - den Chromium-Quellcode !
BEARBEITEN: Habe gerade die Firebug-Quelle überprüft, sie verketten 4 mit Anweisungen für noch mehr Ebenen. Verrückt!
quelle
Ja, ja und ja. Es gibt eine sehr legitime Verwendung. Uhr:
Grundsätzlich sind alle anderen DOM- oder CSS-Hooks eine fantastische Verwendung mit. Es ist nicht so, dass "CloneNode" undefiniert ist und zum globalen Bereich zurückkehrt, es sei denn, Sie haben alles getan, um dies zu ermöglichen.
Crockfords Geschwindigkeitsbeschwerde ist, dass durch mit ein neuer Kontext erstellt wird. Kontexte sind im Allgemeinen teuer. Genau. Wenn Sie jedoch gerade ein div erstellt haben und kein Framework zum Festlegen Ihres CSS zur Verfügung haben und etwa 15 CSS-Eigenschaften manuell einrichten müssen, ist das Erstellen eines Kontexts wahrscheinlich billiger als das Erstellen von Variablen und 15 Dereferenzen:
usw...
quelle
with
. In diesem speziellen Fall können Sie jedoch einfachelement.style.cssText="background: black ; color: blue ; border: 1px solid green"
extend
Methode von jQuery oder Underscore.js erreichen :$.extend(element.style, {fontWeight: 'bold', fontSize: '1.5em', color: '#55d', marginLeft: '2px'})
..css()
Methode ...Sie können eine kleine Hilfsfunktion definieren, um die Vorteile
with
ohne Mehrdeutigkeit zu nutzen:quelle
with_
wenn Sie eine schlammige Doppelversion von sind(function(_){ _.a="foo"; })(object_here);
(die Standardmethode zum Simulieren von Blöcken im C / Java-Stil). Verwenden Sie das stattdessen.Es scheint sich kaum zu lohnen, da Sie Folgendes tun können:
quelle
with
.Ich benutze es nie mit, sehe keinen Grund dafür und empfehle es nicht.
Das Problem dabei
with
ist, dass es zahlreiche lexikalische Optimierungen verhindert, die eine ECMAScript-Implementierung durchführen kann. Angesichts des Aufstiegs schneller JIT-basierter Motoren wird dieses Problem in naher Zukunft wahrscheinlich noch wichtiger.Es sieht vielleicht so aus, als ob
with
es sauberere Konstrukte zulässt (wenn beispielsweise ein neuer Bereich anstelle eines gemeinsamen anonymen Funktionsumschlags eingeführt oder ausführliches Aliasing ersetzt wird), aber es lohnt sich wirklich nicht . Neben einer verminderten Leistung besteht immer die Gefahr, einer Eigenschaft eines falschen Objekts zuzuweisen (wenn eine Eigenschaft für ein Objekt im injizierten Bereich nicht gefunden wird) und möglicherweise fälschlicherweise globale Variablen einzuführen. IIRC, letzteres Problem hat Crockford dazu motiviert, zu empfehlen, es zu vermeidenwith
.quelle
with(){}
Konstrukten haben, wie sie in anderen Antworten hier in modernen Browsern angegeben sind, würde ich gerne sehen Sie!with(){}
: Das Einrichten eines neuen Bereichs mitwith
ist für jeden von mir getesteten Browser enorm teuer. Sie möchten dies in jedem Code vermeiden, der sehr häufig aufgerufen wird. Darüber hinaus zeigte Chrome einen dramatischen Erfolg für jeden Code, der innerhalb eineswith()
Bereichs ausgeführt wird. Interessanterweise hatte der IE die besten Leistungsmerkmale für Code innerhalb vonwith()
Blöcken: Das Ausklammern der Einrichtungskostenwith()
bietet die schnellste Möglichkeit für den Mitgliederzugriff in IE6- und IE8-VMs (obwohl diese VMs insgesamt die langsamsten sind). Gutes Zeug, danke ...with()
ist in Chrome fast eine Größenordnung langsamer und im IE mehr als doppelt so schnell ...!Visual Basic.NET hat eine ähnliche
With
Anweisung. Eine der gebräuchlichsten Methoden ist das schnelle Festlegen einer Reihe von Eigenschaften. Anstatt:, Ich kann schreiben:
Dies ist nicht nur eine Frage der Faulheit. Es sorgt auch für viel besser lesbaren Code. Und im Gegensatz zu JavaScript weist es keine Mehrdeutigkeit auf, da Sie allen von der Anweisung betroffenen
.
Punkten einen (Punkt) voranstellen müssen . Die folgenden beiden unterscheiden sich also deutlich:vs.
Ersteres ist
someObject.Foo
; Letzteres liegtFoo
im Geltungsbereich außerhalbsomeObject
.Ich finde, dass die mangelnde Unterscheidung von JavaScript weitaus weniger nützlich ist als die Variante von Visual Basic, da das Risiko von Mehrdeutigkeiten zu hoch ist. Davon abgesehen
with
ist es immer noch eine leistungsstarke Idee, die zu einer besseren Lesbarkeit führen kann.quelle
Sie können
with
den Inhalt eines Objekts als lokale Variablen in einen Block einfügen, wie dies mit dieser kleinen Vorlagen-Engine der Fall ist .quelle
Die Verwendung von "mit" kann Ihren Code trockener machen.
Betrachten Sie den folgenden Code:
Sie können es wie folgt trocknen:
Ich denke, es hängt davon ab, ob Sie Lesbarkeit oder Ausdruckskraft bevorzugen.
Das erste Beispiel ist besser lesbar und wird wahrscheinlich für den meisten Code empfohlen. Aber der meiste Code ist sowieso ziemlich zahm. Die zweite ist etwas dunkler, verwendet jedoch die Ausdruckskraft der Sprache, um die Codegröße und überflüssige Variablen zu reduzieren.
Ich stelle mir vor, dass Leute, die Java oder C # mögen, den ersten Weg wählen würden (object.member) und diejenigen, die Ruby oder Python bevorzugen, den letzteren wählen würden.
quelle
Ich denke, die offensichtliche Verwendung ist als Abkürzung. Wenn Sie beispielsweise ein Objekt initialisieren, speichern Sie einfach die Eingabe von "ObjectName". Ein bisschen wie Lisp's "With-Slots", mit denen Sie schreiben können
Das ist das gleiche wie schreiben
Es ist offensichtlicher, warum dies eine Verknüpfung ist, als wenn Ihre Sprache "Objectname.foo" zulässt, aber immer noch.
quelle
with-slots
müssen Sie angeben, welche Slots Sie verwenden, während Siewith
alle Slots verwenden, die zur Laufzeit gebunden sind.Aufgrund meiner Erfahrung mit Delphi würde ich sagen, dass die Verwendung mit eine letzte Größenoptimierung sein sollte, die möglicherweise von einer Art Javascript-Minimierungsalgorithmus mit Zugriff auf statische Code-Analyse durchgeführt wird, um die Sicherheit zu überprüfen.
Die Scoping-Probleme, auf die Sie bei der liberalen Verwendung der with- Anweisung stoßen können, können ein königlicher Schmerz in der a ** sein, und ich möchte nicht, dass jemand eine Debugging-Sitzung durchläuft, um herauszufinden, was in Ihrem Code vor sich geht , nur um herauszufinden, dass ein Objektelement oder die falsche lokale Variable anstelle Ihrer von Ihnen beabsichtigten globalen oder äußeren Bereichsvariablen erfasst wurde.
Der VB mit Aussage ist insofern besser, als es die Punkte benötigt, um das Scoping zu disambiguieren, aber das Delphi mit Aussage ist eine geladene Waffe mit einem Haarauslöser, und es sieht für mich so aus, als ob das Javascript ähnlich genug ist, um dieselbe Warnung zu rechtfertigen.
quelle
Die Verwendung mit wird nicht empfohlen und ist im strengen ECMAScript 5-Modus verboten. Die empfohlene Alternative besteht darin, das Objekt, auf dessen Eigenschaften Sie zugreifen möchten, einer temporären Variablen zuzuweisen.
Quelle: Mozilla.org
quelle
Die with-Anweisung kann zum Verringern der Codegröße oder für private Klassenmitglieder verwendet werden. Beispiel:
Die with-Anweisung ist sehr nützlich, wenn Sie den Bereich ändern möchten. Dies ist erforderlich, um einen eigenen globalen Bereich zu haben, den Sie zur Laufzeit bearbeiten können. Sie können Konstanten oder bestimmte Hilfsfunktionen einfügen, die häufig verwendet werden, z. B. "toUpper", "toLower" oder "isNumber", "clipNumber".
Über die schlechte Leistung habe ich so oft gelesen: Das Scoping einer Funktion hat keinen Einfluss auf die Leistung. In meinem FF läuft eine Scoped-Funktion schneller als eine nicht-Scope:
Auf die oben erwähnte Weise hat die with-Anweisung keine negativen Auswirkungen auf die Leistung, aber eine gute, da sie die Codegröße verringert, was sich auf die Speichernutzung auf Mobilgeräten auswirkt.
quelle
Durch die Verwendung von with wird Ihr Code in vielen Implementierungen langsamer, da jetzt alles in einen zusätzlichen Bereich für die Suche eingeschlossen wird. Es gibt keinen legitimen Grund für die Verwendung in JavaScript.
quelle
var obj={a:0,b:0,c:0};var d=+new Date;with(obj){for(var i=0;i<1000000;++i){a+=1;b+=1;c+=1}}+new Date-d;
gibt im Durchschnitt 2500,var obj={a:0,b:0,c:0};var d=+new Date;for(var i=0;i<1000000;++i){obj.a+=1;obj.b+=1;obj.c+=1}+new Date-d;
gibt im Durchschnitt 750, was die Verwendung über 3-mal langsamer macht.with
Code und 903 ohne. Mit diesem winzigen Unterschied würde ich selbst in einer engen Schleife eine Auswahl treffen, die auf der Einfachheit der Codierung und der einfachen Umgestaltung von Fall zu Fall basiert, bevor ich mich um die Leistung kümmere.Ich denke, die with-Anweisung kann nützlich sein, wenn eine Vorlagensprache in JavaScript konvertiert wird. Zum Beispiel JST in base2 , aber ich habe es öfter gesehen.
Ich bin damit einverstanden, dass man dies ohne die with-Anweisung programmieren kann. Aber weil es keine Probleme gibt, ist es eine legitime Verwendung.
quelle
Es ist gut, um Code, der in einer relativ komplizierten Umgebung ausgeführt wird, in einen Container einzufügen: Ich verwende ihn, um eine lokale Bindung für "Fenster" zu erstellen und um Code für einen Webbrowser auszuführen.
quelle
Ich denke, die wörtliche Verwendung des Objekts ist interessant, wie ein Ersatz für die Verwendung eines Verschlusses
oder die mit Aussage gleichbedeutend mit einer Schließung
Ich denke, das eigentliche Risiko besteht darin, versehentlich Variablen zu minimieren, die nicht Teil der with-Anweisung sind. Deshalb gefällt mir das Objektliteral, mit dem übergeben wird. Sie können genau sehen, wie es im hinzugefügten Kontext im Code aussehen wird.
quelle
Ich habe eine "Zusammenführungs" -Funktion erstellt, die einige dieser Unklarheiten mit der
with
Anweisung beseitigt :Ich kann es ähnlich wie verwenden
with
, aber ich kann wissen, dass es keinen Bereich beeinflusst, den ich nicht beeinflussen möchte.Verwendungszweck:
quelle
Für einige kurzen Codestücke, würde Ich mag die trigonometrischen Funktionen wie verwenden
sin
,cos
usw. in Grad - Modus statt im Strahlungsmodus. Zu diesem Zweck verwende ich einAngularDegree
Objekt:Dann kann ich die trigonometrischen Funktionen im Gradmodus ohne weiteres Sprachrauschen in einem
with
Block verwenden:Dies bedeutet: Ich verwende ein Objekt als Sammlung von Funktionen, die ich in einem begrenzten Codebereich für den direkten Zugriff aktiviere. Ich finde das nützlich.
quelle
with
Anweisung auf diese Weise zu verwenden. Sie macht den Code nur schwer lesbar, da Sie nicht wissen, welche Funktion global ist und welche Funktion im Bereich von with object aufgerufen wird Objektbereich dann wird es versuchen, im globalen Namespace darauf zuzugreifenz = Math.atan2( Math.sin(d * Math.PI / 180), Math.cos( pol.lat * Math.PI / 180) * Math.tan( pos.lat * Math.PI / 180 ) - Math.sin( pol.lat * Math.PI / 180 ) * Math.cos( d * Math.PI / 180) ) * 180 / Math.PI;
würde das gleiche Ergebnis liefern, aber es ist der Horror.with
würden.Ich denke, dass der Nutzen von
with
davon abhängen kann, wie gut Ihr Code geschrieben ist. Wenn Sie beispielsweise Code schreiben, der folgendermaßen aussieht:dann könnte man das argumentieren
with
die Lesbarkeit des Codes verbessert:Umgekehrt könnte argumentiert werden, dass Sie gegen das Gesetz von Demeter verstoßen , aber andererseits vielleicht auch nicht. Ich schweife ab =).
Beachten Sie vor allem, dass Douglas Crockford die Verwendung nicht empfiehlt
with
. Ich fordere Sie auf, seinen Blog-Beitragwith
und seine Alternativen hier zu lesen .quelle
Ich sehe nur wirklich nicht, wie die Verwendung von with besser lesbar ist als nur die Eingabe von object.member. Ich denke nicht, dass es weniger lesbar ist, aber ich denke auch nicht, dass es besser lesbar ist.
Wie lassevk sagte, kann ich definitiv sehen, dass die Verwendung mit fehleranfälliger wäre als nur die sehr explizite "object.member" -Syntax.
quelle
Die Validierung eines Formulars in Javascript finden Sie unter W3schools http://www.w3schools.com/js/js_form_validation.asp. Dort wird das Objektformular "gescannt", um eine Eingabe mit dem Namen "email" zu finden.
Aber ich habe es so geändert, dass von JEDEM Formular alle Felder als nicht leer validiert werden, unabhängig vom Namen oder der Anzahl der Felder in einem Formular. Nun, ich habe nur Textfelder getestet.
Aber das with () hat die Sache einfacher gemacht. Hier ist der Code:
quelle
Die Coco- Gabel von CoffeeScript hat ein
with
Schlüsselwort, setzt jedoch einfachthis
(auch beschreibbar wie@
in CoffeeScript / Coco) das Zielobjekt innerhalb des Blocks. Dies beseitigt Mehrdeutigkeiten und erreicht die strikte Einhaltung des ES5-Modus:quelle
Hier ist eine gute Verwendung für
with
: Hinzufügen neuer Elemente zu einem Objektliteral, basierend auf den in diesem Objekt gespeicherten Werten. Hier ist ein Beispiel, das ich heute verwendet habe:Ich hatte eine Reihe möglicher Kacheln (mit Öffnungen nach oben, unten, links oder rechts), die verwendet werden konnten, und ich wollte schnell eine Liste von Kacheln hinzufügen, die zu Beginn des Spiels immer platziert und gesperrt wurden . Ich wollte nicht
types.tbr
für jeden Typ in der Liste weiter tippen, also habe ich nur verwendetwith
.quelle
Sie können mit verwenden, um zu vermeiden, dass Sie arity explizit verwalten müssen, wenn Sie require.js verwenden:
Implementierung von requirejs.declare:
quelle
Wie Andy E in den Kommentaren der Antwort von Shog9 hervorhob, tritt dieses möglicherweise unerwartete Verhalten bei der Verwendung
with
mit einem Objektliteral auf:Nicht, dass unerwartetes Verhalten nicht schon ein Markenzeichen gewesen wäre
with
.Wenn Sie diese Technik wirklich noch verwenden möchten, verwenden Sie mindestens ein Objekt mit einem Null-Prototyp.
Dies funktioniert jedoch nur in ES5 +. Auch nicht benutzen
with
.quelle
Ich arbeite an einem Projekt, mit dem Benutzer Code hochladen können, um das Verhalten von Teilen der Anwendung zu ändern. In diesem Szenario habe ich eine
with
Klausel verwendet, um zu verhindern, dass der Code irgendetwas außerhalb des Bereichs ändert, mit dem sie herumspielen sollen. Der (vereinfachte) Teil des Codes, den ich dazu benutze, ist:Dieser Code stellt (etwas) sicher, dass der benutzerdefinierte Code weder Zugriff auf Objekte mit globalem Gültigkeitsbereich hat, wie z
window
durch einen Abschluss auf eine meiner lokalen Variablen hat.Nur um es weise zu sagen, ich muss immer noch statische Codeprüfungen für den vom Benutzer eingereichten Code durchführen, um sicherzustellen, dass sie keine anderen hinterhältigen Methoden verwenden, um auf den globalen Bereich zuzugreifen. Der folgende benutzerdefinierte Code bietet beispielsweise direkten Zugriff auf
window
:quelle
Meine
läuft darauf hinaus
Können Sie so minderwertigem Code vertrauen? Nein, wir sehen, dass es absolut unlesbar gemacht wurde. Dieses Beispiel beweist unbestreitbar, dass keine With-Statement erforderlich ist, wenn ich die Lesbarkeit richtig nehme;)
quelle