Wie erstelle ich einen Namespace in JavaScript, damit meine Objekte und Funktionen nicht von anderen gleichnamigen Objekten und Funktionen überschrieben werden? Ich habe folgendes verwendet:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
Gibt es eine elegantere oder prägnantere Möglichkeit, dies zu tun?
javascript
namespaces
javascript-namespaces
Scott McKenzie
quelle
quelle
Antworten:
Ich mag das:
quelle
MyApp
, zBMyApp.Views.Profile = {}
eher alsMyApp.users = {}
undMyViews.Profile = {}
. Nicht unbedingt, dass es nur zwei Ebenen Tiefe geben sollte.Ich verwende den Ansatz auf der Enterprise jQuery-Site :
Hier ist ihr Beispiel, das zeigt, wie private und öffentliche Eigenschaften und Funktionen deklariert werden. Alles wird als selbstausführende anonyme Funktion ausgeführt.
Wenn Sie also auf eines der öffentlichen Mitglieder zugreifen möchten, gehen Sie einfach
skillet.fry()
oderskillet.ingredients
.Was wirklich cool ist, ist, dass Sie den Namespace jetzt mit genau derselben Syntax erweitern können.
Das dritte
undefined
Argumentquelle
undefined
Argument ist die Quelle der Wertvariablenundefined
. Während der Arbeit mit älteren Browsern / Javascript-Standard (Ecmascript 5, Javascript <1.8.5 ~ Firefox 4) ist die Variable für den globalen Bereichundefined
beschreibbar, sodass jeder ihren Wert neu schreiben kann. Wenn Sie ein drittes zusätzliches Argument hinzufügen, das Sie nicht übergeben, wird es wertvollundefined
. Sie haben also einen Namespace-Bereich erstellt,undefined
der von externen Quellen nicht neu geschrieben wird.window.skillet = window.skillet || {}
ist, dass mehrere Skripte sicher zum gleichen Namespace hinzugefügt werden können, wenn sie nicht im Voraus wissen, in welcher Reihenfolge sie ausgeführt werden. Dies kann hilfreich sein, wenn Sie Ihre Skripteinschlüsse willkürlich neu anordnen möchten, ohne Ihren Code zu beschädigen, oder wenn Sie Skripte asynchron mit dem Attribut async laden möchten und daher keine Garantie für die Ausführungsreihenfolge haben. Siehe stackoverflow.com/questions/6439579/…Eine andere Möglichkeit, die ich für etwas weniger restriktiv halte als die Objektliteralform, ist folgende:
Die oben ist ziemlich genau wie das Modul Muster und ob Sie es mögen oder nicht , es können Sie alle Ihre Funktionen als öffentlich zu exponieren, während die starre Struktur eines Objektliteral zu vermeiden.
quelle
ns().publicFunction()
, das heißt ...ns.publicFunction()
funktioniert.new
Schlüsselworts vor demfunction
Schlüsselwort notwendig . Grundsätzlich deklariert es eine anonyme Funktion (und als Funktion ist es auch ein Konstruktor) und ruft sie dann sofort als Konstruktor mit aufnew
. Daher ist der endgültige Wert, der darin gespeichertns
wird, eine (eindeutige) Instanz dieses anonymen Konstruktors. Hoffe es macht Sinn.Ja. Zum Beispiel:
dann kannst du haben
quelle
var your_namespace = your_namespace = your_namespace || {}
Normalerweise baue ich es in einem Verschluss:
Mein Stil hat sich im Laufe der Jahre seit dem Schreiben dieses Artikels geringfügig geändert, und jetzt schreibe ich den Abschluss folgendermaßen:
Auf diese Weise finde ich die öffentliche API und Implementierung leichter zu verstehen. Stellen Sie sich die return-Anweisung als öffentliche Schnittstelle zur Implementierung vor.
quelle
MYNS.subns = MYNS.subns || {}
?var foo = function
undfunction foo
ähnlich sind, privat sein; Aufgrund der dynamisch typisierten Natur von JavaScript ist letzteres etwas schneller, da einige Anweisungen in den Pipelines der meisten Interpreter übersprungen werden. Mitvar foo
muss das Typsystem aufgerufen werden, um herauszufinden, welcher Typ dieser Variablen zugewiesen ist, während mitfunction foo
das Typsystem automatisch weiß, dass es sich um eine Funktion handelt, sodass einige Funktionsaufrufe übersprungen werden, was zu weniger Aufrufen von CPU-Anweisungen wie führtjmp
,pushq
,popq
, usw., die zu einer kürzeren Pipeline CPU übersetzt.function foo
Syntax besser lesbar. Und ich mag immer noch meine Version.Da Sie möglicherweise verschiedene JavaScript-Dateien schreiben und diese später in einer Anwendung kombinieren oder nicht kombinieren, muss jede in der Lage sein, das Namespace-Objekt wiederherzustellen oder zu erstellen, ohne die Arbeit anderer Dateien zu beschädigen ...
Eine Datei beabsichtigt möglicherweise, den Namespace zu verwenden
namespace.namespace1
:Eine andere Datei möchte möglicherweise den Namespace verwenden
namespace.namespace2
:Diese beiden Dateien können zusammen oder getrennt leben, ohne zu kollidieren.
quelle
So macht es Stoyan Stefanov in seinem JavaScript- Musterbuch, das ich als sehr gut empfunden habe (es zeigt auch, wie er Kommentare macht, die eine automatisch generierte API-Dokumentation ermöglichen, und wie man dem Prototyp eines benutzerdefinierten Objekts eine Methode hinzufügt):
quelle
Ich benutze diesen Ansatz:
Externer Code kann dann sein:
quelle
ns = ns || {}
es defensiver erscheinen mag, kann es zu anderen unerwarteten Ergebnissen führen.Dies ist eine Fortsetzung des Links von user106826 zu Namespace.js. Es scheint, dass das Projekt auf GitHub verschoben wurde . Es ist jetzt Smith / Namespacedotjs .
Ich habe diesen einfachen JavaScript-Helfer für mein kleines Projekt verwendet und bisher scheint er leicht und dennoch vielseitig genug zu sein, um Namespace und zu verarbeiten Laden von Modulen / Klassen . Es wäre großartig, wenn ich ein Paket in einen Namespace meiner Wahl importieren könnte, nicht nur in den globalen Namespace ... seufz, aber das ist nicht der Punkt.
Sie können den Namespace deklarieren und dann Objekte / Module in diesem Namespace definieren:
Eine andere Möglichkeit besteht darin, den Namespace und seinen Inhalt sofort zu deklarieren:
Weitere Anwendungsbeispiele finden Sie in der Datei example.js in der Quelle .
quelle
Stichprobe:
Sie können optional eine
local
Variable deklarierensame
, wieself
und zuweisen,local.onTimeout
wenn Sie möchten, dass sie privat ist.quelle
Sie können eine einfache Funktion zum Bereitstellen von Namespaces deklarieren.
quelle
Wenn Sie den privaten Bereich benötigen:
Andernfalls, wenn Sie den privaten Bereich niemals verwenden werden:
quelle
Das Modulmuster wurde ursprünglich als eine Möglichkeit definiert, sowohl private als auch öffentliche Kapselung für Klassen in konventioneller Softwareentwicklung bereitzustellen.
Wenn Sie mit dem Modulmuster arbeiten, kann es hilfreich sein, eine einfache Vorlage zu definieren, die wir für den Einstieg verwenden. Hier ist eine, die Namensabstände, öffentliche und private Variablen abdeckt.
In JavaScript wird das Modulmuster verwendet, um das Konzept von Klassen weiter zu emulieren, sodass wir sowohl öffentliche / private Methoden als auch Variablen in ein einzelnes Objekt aufnehmen können, wodurch bestimmte Teile vor dem globalen Bereich geschützt werden. Dies führt zu einer Verringerung der Wahrscheinlichkeit, dass unsere Funktionsnamen mit anderen Funktionen in Konflikt stehen, die in zusätzlichen Skripten auf der Seite definiert sind.
Vorteile
Warum ist das Modulmuster eine gute Wahl? Für Entwickler ist es zunächst viel sauberer, wenn sie einen objektorientierten Hintergrund haben, als die Idee einer echten Kapselung, zumindest aus JavaScript-Sicht.
Zweitens werden private Daten unterstützt. Im Modulmuster können öffentliche Teile unseres Codes die privaten Teile berühren, die Außenwelt kann jedoch die privaten Teile der Klasse nicht berühren.
Nachteile
Die Nachteile des Modulmusters bestehen darin, dass wir, da wir sowohl auf öffentliche als auch auf private Mitglieder unterschiedlich zugreifen, wenn wir die Sichtbarkeit ändern möchten, tatsächlich Änderungen an jedem Ort vornehmen müssen, an dem das Mitglied verwendet wurde.
Wir können auch nicht auf private Mitglieder in Methoden zugreifen, die dem Objekt zu einem späteren Zeitpunkt hinzugefügt werden . In vielen Fällen ist das Modulmuster jedoch immer noch sehr nützlich und kann bei korrekter Verwendung sicherlich die Struktur unserer Anwendung verbessern.
Das aufschlussreiche Modulmuster
Nachdem wir das Modulmuster etwas besser kennen, schauen wir uns eine leicht verbesserte Version an - das Heilungsmodul von Christian Heilmann.
Das Revealing Module-Muster entstand, als Heilmann frustriert war, dass er den Namen des Hauptobjekts wiederholen musste, wenn wir eine öffentliche Methode von einer anderen aufrufen oder auf öffentliche Variablen zugreifen wollten. Er mochte auch die Anforderung des Modulmusters, wechseln zu müssen, nicht wörtliche Notation für die Dinge zu beanstanden, die er öffentlich machen wollte.
Das Ergebnis seiner Bemühungen war ein aktualisiertes Muster, bei dem wir einfach alle unsere Funktionen und Variablen im privaten Bereich definieren und ein anonymes Objekt mit Zeigern auf die private Funktionalität zurückgeben, die wir als öffentlich offenbaren wollten.
Ein Beispiel für die Verwendung des Revealing Module-Musters finden Sie unten
Vorteile
Dieses Muster ermöglicht eine konsistentere Syntax unserer Skripte. Außerdem wird am Ende des Moduls klarer, auf welche unserer Funktionen und Variablen öffentlich zugegriffen werden kann, was die Lesbarkeit erleichtert.
Nachteile
Ein Nachteil dieses Musters besteht darin, dass, wenn sich eine private Funktion auf eine öffentliche Funktion bezieht, diese öffentliche Funktion nicht überschrieben werden kann, wenn ein Patch erforderlich ist. Dies liegt daran, dass die private Funktion weiterhin auf die private Implementierung verweist und das Muster nicht für öffentliche Mitglieder gilt, sondern nur für Funktionen.
Öffentliche Objektmitglieder, die auf private Variablen verweisen, unterliegen ebenfalls den obigen No-Patch-Regelhinweisen.
quelle
Ich habe einen Namespace erstellt, der von Erlangs Modulen inspiriert ist. Es ist ein sehr funktionaler Ansatz, aber so schreibe ich heutzutage meinen JavaScript-Code.
Es gibt einem Abschluss einen globalen Namespace und macht eine definierte Menge von Funktionen innerhalb dieses Abschlusses verfügbar.
quelle
Nachdem ich mehrere meiner Bibliotheken in verschiedene Projekte portiert habe und ständig den Namespace der obersten Ebene (statisch benannt) ändern musste, habe ich diese kleine (Open Source) Hilfsfunktion zum Definieren von Namespaces verwendet.
Eine Beschreibung der Vorteile finden Sie in meinem Blogbeitrag . Den Quellcode können Sie hier abrufen .
Einer der Vorteile, die ich sehr mag, ist die Isolation zwischen Modulen in Bezug auf die Ladereihenfolge. Sie können sich auf ein externes Modul beziehen, bevor es geladen wird. Die Objektreferenz, die Sie erhalten, wird ausgefüllt, sobald der Code verfügbar ist.
quelle
Ich verwende die folgende Syntax für den Namespace.
jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/
quelle
Ich bin 7 Jahre zu spät zur Party, habe aber vor 8 Jahren ziemlich viel daran gearbeitet:
Es ist wichtig, in der Lage zu sein, auf einfache und effiziente Weise mehrere verschachtelte Namespaces zu erstellen, um eine komplexe Webanwendung organisiert und verwaltbar zu halten. Dabei muss der globale JavaScript-Namespace beachtet werden (um eine Verschmutzung des Namespaces zu vermeiden) und dabei keine vorhandenen Objekte im Namespace-Pfad überlastet werden .
Aus dem oben Gesagten war dies meine Lösung von ca. 2008:
Dies erstellt keinen Namespace, bietet jedoch eine Funktion zum Erstellen von Namespaces.
Dies kann zu einem minimierten Einzeiler verdichtet werden:
Anwendungsbeispiel:
Oder als eine Aussage:
Beides wird dann ausgeführt als:
Wenn Sie keine Unterstützung für ältere Browser benötigen, eine aktualisierte Version:
Jetzt wäre ich misstrauisch, mich
namespace
dem globalen Namespace selbst auszusetzen . (Schade, dass die Basissprache dies nicht für uns bereitstellt!) Daher würde ich dies normalerweise selbst in einem Abschluss verwenden, wie zum Beispiel:In einer größeren Anwendung muss dies nur einmal zu Beginn eines Seitenladens definiert werden (für clientbasierte Webanwendungen). Zusätzliche Dateien können dann die Namespace-Funktion wiederverwenden, wenn sie beibehalten werden (oben als "optional" enthalten). Im schlimmsten Fall, wenn diese Funktion einige Male neu deklariert wird, sind es nur wenige Codezeilen und weniger, wenn sie minimiert werden.
quelle
Ich denke, Sie alle verwenden zu viel Code für ein so einfaches Problem. Dafür muss kein Repo gemacht werden. Hier ist eine einzeilige Funktion.
Versuch es :
quelle
Ich mag die Lösung von Jaco Pretorius, aber ich wollte das Schlüsselwort "this" ein bisschen nützlicher machen, indem ich es auf das Modul- / Namespace-Objekt zeige. Meine Version der Pfanne:
quelle
Mein Lieblingsmuster ist in letzter Zeit so geworden:
Natürlich kann die Rückgabe am Ende erfolgen, aber wenn nur Funktionsdeklarationen folgen, ist es viel einfacher zu erkennen, worum es im Namespace geht und welche API verfügbar gemacht wird.
Das Muster der Verwendung von Funktionsausdrücken in solchen Fällen führt dazu, dass nicht bekannt ist, welche Methoden verfügbar gemacht werden, ohne den gesamten Code zu durchlaufen.
quelle
namespace.a();
Wenn Sie ein Makefile verwenden, können Sie dies tun.
Ich bevorzuge es sowieso, ein Makefile zu verwenden, sobald ich ungefähr 1000 Zeilen erreicht habe, da ich große Codebereiche effektiv auskommentieren kann, indem ich eine einzelne Zeile im Makefile entferne. Es macht es einfach, mit Sachen herumzuspielen. Bei dieser Technik wird der Namespace auch nur einmal im Vorspiel angezeigt, sodass er leicht geändert werden kann und Sie ihn nicht ständig im Bibliothekscode wiederholen müssen.
Ein Shell-Skript für die Live-Entwicklung im Browser bei Verwendung eines Makefiles:
Fügen Sie dies als Make-Task 'go' hinzu und Sie können 'make go', um Ihren Build während des Codierens auf dem neuesten Stand zu halten.
quelle
Eine ziemliche Fortsetzung der Antwort von Ionuț G. Stan, zeigt jedoch die Vorteile von übersichtlichem Code mithilfe von
var ClassFirst = this.ClassFirst = function() {...}
, wodurch das Closure Scoping von JavaScript für weniger Namespace-Unordnung für Klassen im selben Namespace genutzt wird.Ausgabe:
quelle
Ich habe eine andere Namespace-Bibliothek geschrieben, die ein bisschen mehr wie Pakete / Einheiten in anderen Sprachen funktioniert. Sie können ein Paket mit JavaScript-Code und die Referenz dieses Pakets aus anderem Code erstellen:
Datei hello.js
Datei Example.js
Nur die zweite Datei muss auf der Seite enthalten sein. Seine Abhängigkeiten (Datei hello.js in diesem Beispiel die ) werden automatisch geladen, und die aus diesen Abhängigkeiten exportierten Objekte werden zum Auffüllen der Argumente der Rückruffunktion verwendet.
Sie finden das zugehörige Projekt in Packages JS .
quelle
Wir können es auf diese Weise unabhängig verwenden:
quelle
Meine Gewohnheit ist es, die Funktion myName () als Eigenschaftsspeicher und dann var myName zu verwenden als "Methoden" zu verwenden ...
Ob das legitim genug ist oder nicht, schlag mich! Ich verlasse mich die ganze Zeit auf meine PHP-Logik und die Dinge funktionieren einfach. : D.
if (this !== that) myObj.fName1(); else myObj.fName2();
Verweis darauf: JavaScript: Objekt mit Object.create () erstellen
quelle
In JavaScript gibt es keine vordefinierten Methoden zur Verwendung von Namespaces. In JavaScript müssen wir unsere eigenen Methoden erstellen, um NameSpaces zu definieren. Hier ist ein Verfahren, das wir in Oodles-Technologien befolgen.
Registrieren eines Namensraums Im Folgenden finden Sie die Funktion zum Registrieren eines Namensraums
Um einen Namespace zu registrieren, rufen Sie einfach die obige Funktion mit dem Argument als durch
'.'
(Punkt) getrenntem Namensraum auf . Zum Beispiel Lassen Sie Ihren Anwendungsnamen Unmengen sein. Sie können einen Namespace mit der folgenden Methode erstellenGrundsätzlich wird Ihre NameSpaces-Struktur wie unten im Backend erstellt:
In der obigen Funktion haben Sie einen Namespace namens
"oodles.HomeUtilities"
und registriert"oodles.GlobalUtilities"
. Um diese Namespaces aufzurufen, erstellen wir eine Variable, dh var$OHU
und var$OGU
.Diese Variablen sind nichts anderes als ein Alias für die Initialisierung des Namespace. Wenn Sie nun eine Funktion deklarieren, die zu
HomeUtilities
Ihnen gehört, wird sie wie folgt deklariert:Oben ist die Initialisierung des Funktionsnamens aufgeführt, die in einen Namespace eingefügt wird
$OHU
. und diese Funktion an einer beliebigen Stelle in den Skriptdateien aufzurufen. Verwenden Sie einfach den folgenden Code.Ebenso mit den anderen NameSpaces.
Ich hoffe es hilft.
quelle
JavaScript unterstützt standardmäßig keinen Namespace. Wenn Sie also ein Element (Funktion, Methode, Objekt, Variable) erstellen, wird es global und verschmutzt den globalen Namespace. Nehmen wir ein Beispiel für die Definition von zwei Funktionen ohne Namespace.
Es wird immer die zweite Funktionsdefinition aufgerufen. In diesem Fall löst der Namespace das Problem der Namenskollision.
quelle