1078 Stimmen

Wie deklariere ich einen Namespace in JavaScript?

Wie erstelle ich einen Namespace in JavaScript, damit meine Objekte und Funktionen nicht von anderen gleichnamigen Objekten und Funktionen überschrieben werden? Ich habe das Folgende verwendet:

if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}

Gibt es eine elegantere oder prägnantere Methode, dies zu tun?

21 Stimmen

Ich kann sehen, wo Sie mit der Überprüfung gehen, um zu sehen, wenn der Namespace genommen wird, aber da das Objekt nicht erstellt werden, wenn dies fehlschlägt, denke ich, der bessere Ansatz ist zu warnen, wenn der Namespace genommen wird. Offen gesagt sollte dies einfach nicht in den meisten JS-Situationen passieren und sollte schnell in der Entwicklung gefangen werden.

19 Stimmen

Nehmen Sie einen "Namespace" der obersten Ebene (Fenstereigenschaft). Besitzen Sie ihn. Konflikte sollten bereits in der Testphase erkannt werden. Machen Sie sich nicht die Mühe, all diese "Was wäre wenn"-Prüfungen hinzuzufügen. Es ist ein fatales Problem für doppelte "Namensräume" und sollte als solches behandelt werden . Sie können einen Ansatz wie jQuery verfolgen, um das Bewohnen eines benutzerdefinierten "Namespace" zu ermöglichen; aber dies ist immer noch eine Frage der Entwurfszeit.

0 Stimmen

Siehe auch stackoverflow.com/questions/2102591/ bei Leistungsproblemen

18voto

Divyanshu Rawat Punkte 3489

Das Modulmuster wurde ursprünglich als eine Möglichkeit definiert, in der konventionellen Softwareentwicklung sowohl eine private als auch eine öffentliche Kapselung für Klassen bereitzustellen.

Bei der Arbeit mit dem Modulmuster kann es nützlich 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 Modul-Muster verwendet, um das Konzept der Klassen weiter zu emulieren, so dass wir in der Lage sind, sowohl öffentliche/private Methoden als auch Variablen in ein einziges Objekt einzubinden und so bestimmte Teile vom globalen Bereich abzuschirmen. Dadurch verringert sich die Wahrscheinlichkeit, dass unsere Funktionsnamen mit anderen Funktionen in Konflikt geraten, die in zusätzlichen Skripten auf der Seite definiert sind.

var myNamespace = (function () {

  var myPrivateVar, myPrivateMethod;

  // A private counter variable
  myPrivateVar = 0;

  // A private function which logs any arguments
  myPrivateMethod = function( foo ) {
      console.log( foo );
  };

  return {

    // A public variable
    myPublicVar: "foo",

    // A public function utilizing privates
    myPublicFunction: function( bar ) {

      // Increment our private counter
      myPrivateVar++;

      // Call our private method using bar
      myPrivateMethod( bar );

    }
  };

})();

Vorteile

Warum ist das Modulmuster eine gute Wahl? Zunächst einmal ist es für Entwickler, die aus einem objektorientierten Hintergrund kommen, viel übersichtlicher als die Idee einer echten Kapselung, zumindest aus der Sicht von JavaScript.

Zweitens unterstützt es private Daten - im Modulmuster können also öffentliche Teile unseres Codes die privaten Teile berühren, aber die Außenwelt kann die privaten Teile der Klasse nicht berühren.

Benachteiligungen

Der Nachteil des Modulmusters besteht darin, dass wir, wenn wir die Sichtbarkeit ändern wollen, an jeder Stelle, an der das Element verwendet wurde, Änderungen vornehmen müssen, da wir auf öffentliche und private Elemente unterschiedlich zugreifen.

Wir können auch nicht auf private Mitglieder in Methoden zugreifen, die dem Objekt zu einem späteren Zeitpunkt hinzugefügt werden . Dennoch ist das Modul-Muster in vielen Fällen immer noch recht nützlich und hat bei richtiger Anwendung durchaus das Potenzial, die Struktur unserer Anwendung zu verbessern.

Das aufdeckende Modul-Muster

Nachdem wir nun etwas vertrauter mit dem Modulmuster sind, wollen wir uns eine leicht verbesserte Version ansehen - Christian Heilmanns Revealing Module Muster.

Das Revealing Module-Muster entstand, weil Heilmann frustriert war, dass er den Namen des Hauptobjekts wiederholen musste, wenn er eine öffentliche Methode von einer anderen aus aufrufen oder auf öffentliche Variablen zugreifen wollte, und ihm gefiel auch nicht, dass er für die Dinge, die er öffentlich machen wollte, zur Objektliteralschreibweise wechseln musste.

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 offenlegen wollten.

Ein Beispiel für die Verwendung des Revealing Module-Musters finden Sie unten

var myRevealingModule = (function () {

        var privateVar = "Ben Cherry",
            publicVar = "Hey there!";

        function privateFunction() {
            console.log( "Name:" + privateVar );
        }

        function publicSetName( strName ) {
            privateVar = strName;
        }

        function publicGetName() {
            privateFunction();
        }

        // Reveal public pointers to
        // private functions and properties

        return {
            setName: publicSetName,
            greeting: publicVar,
            getName: publicGetName
        };

    })();

myRevealingModule.setName( "Paul Kinlan" );

Vorteile

Durch dieses Muster wird die Syntax unserer Skripte einheitlicher. Außerdem wird am Ende des Moduls deutlicher, auf welche unserer Funktionen und Variablen öffentlich zugegriffen werden kann, was die Lesbarkeit erleichtert.

Benachteiligungen

Ein Nachteil dieses Musters ist, dass, wenn eine private Funktion auf eine öffentliche Funktion verweist, diese öffentliche Funktion nicht überschrieben werden kann, wenn ein Patch erforderlich ist. Das liegt daran, dass die private Funktion weiterhin auf die private Implementierung verweist und das Muster nicht für öffentliche Mitglieder, sondern nur für Funktionen gilt.

Für öffentliche Objektmitglieder, die sich auf private Variablen beziehen, gilt ebenfalls die oben erwähnte No-Patch-Regel.

17voto

Tadej Punkte 5745

Wenn Sie den privaten Bereich benötigen:

var yourNamespace = (function() {

  //Private property
  var publicScope = {};

  //Private property
  var privateProperty = "aaa"; 

  //Public property
  publicScope.publicProperty = "bbb";

  //Public method
  publicScope.publicMethod = function() {
    this.privateMethod();
  };

  //Private method
  function privateMethod() {
    console.log(this.privateProperty);
  }

  //Return only the public parts
  return publicScope;
}());

yourNamespace.publicMethod();

sonst, wenn Sie den privaten Bereich nie benutzen werden:

var yourNamespace = {};

yourNamespace.publicMethod = function() {
    // Do something...
};

yourNamespace.publicMethod2 = function() {
    // Do something...
};

yourNamespace.publicMethod();

15voto

dnemoga Punkte 214

Sie können eine einfache Funktion deklarieren, um Namespaces bereitzustellen.

function namespace(namespace) {
    var object = this, tokens = namespace.split("."), token;

    while (tokens.length > 0) {
        token = tokens.shift();

        if (typeof object[token] === "undefined") {
            object[token] = {};
        }

        object = object[token];
    }

    return object;
}

// Usage example
namespace("foo.bar").baz = "I'm a value!";

10voto

ziesemer Punkte 26796

Ich bin zwar 7 Jahre zu spät dran, habe aber vor 8 Jahren schon einiges in dieser Richtung unternommen:

Es ist wichtig, mehrere verschachtelte Namespaces einfach und effizient erstellen zu können, um eine komplexe Webanwendung übersichtlich und verwaltbar zu halten und dabei den globalen JavaScript-Namespace zu respektieren (Vermeidung von Namespace-Verschmutzung) und dabei keine vorhandenen Objekte im Namespace-Pfad zu verletzen.

Nach den obigen Ausführungen war dies meine Lösung aus dem Jahr 2008:

var namespace = function(name, separator, container){
  var ns = name.split(separator || '.'),
    o = container || window,
    i,
    len;
  for(i = 0, len = ns.length; i < len; i++){
    o = o[ns[i]] = o[ns[i]] || {};
  }
  return o;
};

Damit wird kein Namespace erstellt, sondern eine Funktion zum Erstellen von Namespaces bereitgestellt.

Dies kann zu einem kurzen Einzeiler verdichtet werden:

var namespace=function(c,f,b){var e=c.split(f||"."),g=b||window,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g};

Beispiel für die Verwendung:

namespace("com.example.namespace");
com.example.namespace.test = function(){
  alert("In namespaced function.");
};

Oder, wie eine Aussage:

namespace("com.example.namespace").test = function(){
  alert("In namespaced function.");
};

Entweder wird dann als ausgeführt:

com.example.namespace.test();

Wenn Sie keine Unterstützung für ältere Browser benötigen, sollten Sie eine aktualisierte Version verwenden:

const namespace = function(name, separator, container){
    var o = container || window;
    name.split(separator || '.').forEach(function(x){
        o = o[x] = o[x] || {};
    });
    return o;
};

Nun, ich wäre vorsichtig mit der Enthüllung namespace in den globalen Namespace selbst. (Schade, dass die Basissprache dies nicht für uns bereitstellt!) Also würde ich dies normalerweise selbst in einer Schließung verwenden, wie z. B.:

(function(){
    const namespace = function(name, separator, container){
        var o = container || window;
        name.split(separator || '.').forEach(function(x){
            o = o[x] = o[x] || {};
        });
        return o;
    };
    const ns = namespace("com.ziesemer.myApp");

    // Optional:
    ns.namespace = ns;

    // Further extend, work with ns from here...
}());

console.log("\"com\":", com);

In einer größeren Anwendung muss dies nur einmal zu Beginn des Seitenladens (bei clientbasierten Webanwendungen) definiert werden. Zusätzliche Dateien können dann die Namensraumfunktion wiederverwenden, wenn sie beibehalten wird (oben als "optional" angegeben). Im schlimmsten Fall, wenn diese Funktion ein paar Mal neu deklariert wird, sind es nur ein paar Zeilen Code, und noch weniger, wenn sie minimiert wird.

9voto

The Who Punkte 6414

Ich habe Namensraum die von Erlangs Modulen inspiriert ist. Es ist ein sehr funktionaler Ansatz, aber das ist, wie ich meinen JavaScript-Code heutzutage schreibe.

Sie gibt einer Closure einen globalen Namensraum und stellt eine definierte Menge von Funktionen innerhalb dieser Closure zur Verfügung.

(function(){

  namespace("images", previous, next);
  // ^^ This creates or finds a root object, images, and binds the two functions to it.
  // It works even though those functions are not yet defined.

  function previous(){ ... }

  function next(){ ... }

  function find(){ ... } // A private function

})();

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X