data - windows document javascript




Come posso dichiarare un namespace in JavaScript? (18)

C'è un modo più elegante o sintetico di farlo?

Sì. Per esempio:

var your_namespace = your_namespace || {};

allora puoi averlo

var your_namespace = your_namespace || {};
your_namespace.Foo = {toAlert:'test'};
your_namespace.Bar = function(arg) 
{
    alert(arg);
};
with(your_namespace)
{
   Bar(Foo.toAlert);
}

Come posso creare uno spazio dei nomi in JavaScript in modo che i miei oggetti e le mie funzioni non vengano sovrascritti da altri oggetti e funzioni con lo stesso nome? Ho usato il seguente:

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

C'è un modo più elegante o sintetico di farlo?


È possibile dichiarare una semplice funzione per fornire spazi dei nomi.

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!";


Dopo aver trasferito molte delle mie librerie a diversi progetti e aver dovuto cambiare costantemente lo spazio dei nomi di livello superiore (con nome statico), ho deciso di utilizzare questa piccola funzione di supporto (open source) per definire gli spazi dei nomi.

global_namespace.Define('startpad.base', function(ns) {
    var Other = ns.Import('startpad.other');
    ....
});

Descrizione dei benefici sono sul mio post del blog . Puoi prendere il codice sorgente qui .

Uno dei vantaggi che mi piace davvero è l'isolamento tra i moduli rispetto all'ordine di caricamento. È possibile fare riferimento a un modulo esterno PRIMA che sia caricato. E il riferimento all'oggetto che ottieni sarà compilato quando il codice è disponibile.


Ho creato un namespace ispirato ai moduli di Erlang. È un approccio molto funzionale, ma è così che scrivo il mio codice JavaScript in questi giorni.

Dà alla chiusura uno spazio dei nomi globale e espone una serie di funzioni definite all'interno di quella chiusura.

(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

})();

Il mio schema preferito è diventato ultimamente questo:

var namespace = (function() {
  
  // expose to public
  return {
    a: internalA,
    c: internalC
  }

  // all private
  
  /**
   * Full JSDoc
   */
  function internalA() {
    // ...
  }
  
  /**
   * Full JSDoc
   */
  function internalB() {
    // ...
  }
  
  /**
   * Full JSDoc
   */
  function internalC() {
    // ...
  }
  
  /**
   * Full JSDoc
   */
  function internalD() {
    // ...
  }
  
})();

Naturalmente, il reso può essere alla fine, ma se solo le dichiarazioni di funzione lo seguono, è molto più facile vedere di cosa si tratta lo spazio dei nomi e quale API è esposta.

Il modello di utilizzo delle espressioni di funzione in tali casi risulta non essere in grado di sapere quali metodi vengono esposti senza andare oltre l'intero codice.


Io uso l'approccio trovato sul sito jQuery Enterprise :

Ecco il loro esempio che mostra come dichiarare proprietà e funzioni private e pubbliche. Tutto è fatto come una funzione anonima autoeseguibile.

(function( skillet, $, undefined ) {
    //Private Property
    var isHot = true;

    //Public Property
    skillet.ingredient = "Bacon Strips";

    //Public Method
    skillet.fry = function() {
        var oliveOil;

        addItem( "\t\n Butter \n\t" );
        addItem( oliveOil );
        console.log( "Frying " + skillet.ingredient );
    };

    //Private Method
    function addItem( item ) {
        if ( item !== undefined ) {
            console.log( "Adding " + $.trim(item) );
        }
    }
}( window.skillet = window.skillet || {}, jQuery ));

Quindi, se vuoi accedere a uno dei membri pubblici, vai su skillet.fry() o skillet.ingredients .

Quello che è veramente interessante è che ora puoi estendere lo spazio dei nomi usando la stessa sintassi esatta.

//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
    //Private Property
    var amountOfGrease = "1 Cup";

    //Public Method
    skillet.toString = function() {
        console.log( skillet.quantity + " " +
                     skillet.ingredient + " & " +
                     amountOfGrease + " of Grease" );
        console.log( isHot ? "Hot" : "Cold" );
    };
}( window.skillet = window.skillet || {}, jQuery ));

Il terzo argomento undefined

Il terzo argomento undefined è la fonte della variabile di valore undefined . Non sono sicuro che sia ancora pertinente oggi, ma mentre si lavora con i vecchi browser / standard JavaScript (ecmascript 5, javascript <1.8.5 ~ firefox 4), la variabile global-scope undefined è scrivibile, quindi chiunque potrebbe riscrivere il suo valore. Il terzo argomento (quando non viene passato un valore) crea una variabile denominata undefined che ha ambito per lo spazio dei nomi / funzione. Poiché non è stato passato alcun valore quando è stato creato lo spazio dei nomi, il valore predefinito è il valore undefined .


Io uso la seguente sintassi per lo spazio dei nomi.

var MYNamespace = MYNamespace|| {};

 MYNamespace.MyFirstClass = function (val) {
        this.value = val;
        this.getValue = function(){
                          return this.value;
                       };
    }

var myFirstInstance = new MYNamespace.MyFirstClass(46);
alert(myFirstInstance.getValue());

jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/


Mi piace la soluzione di Jaco Pretorius, ma volevo rendere la parola chiave "this" un po 'più utile puntandola all'oggetto modulo / spazio dei nomi. La mia versione di skillet:

(function ($, undefined) {

    console.log(this);

}).call(window.myNamespace = window.myNamespace || {}, jQuery);

Mi piace questo:

var yourNamespace = {

    foo: function() {
    },

    bar: function() {
    }
};

...

yourNamespace.foo();

Poiché puoi scrivere diversi file di JavaScript e in seguito combinarli o non combinarli in un'applicazione, ognuno deve essere in grado di recuperare o costruire l'oggetto dello spazio dei nomi senza danneggiare il lavoro di altri file ...

Un file potrebbe voler utilizzare lo spazio namespace.namespace1 nomi namespace.namespace1 :

namespace = window.namespace || {};
namespace.namespace1 = namespace.namespace1 || {};

namespace.namespace1.doSomeThing = function(){}

Un altro file potrebbe voler utilizzare lo spazio namespace.namespace2 nomi namespace.namespace2 :

namespace = window.namespace || {};
namespace.namespace2 = namespace.namespace2 || {};

namespace.namespace2.doSomeThing = function(){}

Questi due file possono convivere o separarsi senza scontrarsi.


Questo è il seguito del collegamento di user106826 a Namespace.js. Sembra che il progetto sia passato a GitHub . Ora è smith/namespacedotjs .

Ho usato questo semplice helper JavaScript per il mio piccolo progetto e finora sembra essere leggero ma abbastanza versatile da gestire il namespacing e il caricamento di moduli / classi. Sarebbe bello se mi permettesse di importare un pacchetto in uno spazio dei nomi a mia scelta, non solo il namespace globale ... sigh, ma questo è oltre il punto.

Permette di dichiarare lo spazio dei nomi, quindi definire oggetti / moduli in quello spazio dei nomi:

Namespace('my.awesome.package');
my.awesome.package.WildClass = {};

Un'altra opzione è dichiarare subito lo spazio dei nomi e il suo contenuto:

Namespace('my.awesome.package', {
    SuperDuperClass: {
        saveTheDay: function() {
            alert('You are welcome.');
        }
    }
});

Per ulteriori esempi di utilizzo, guarda il file example.j nel sorgente .


Sono 7 anni in ritardo per la festa, ma ho fatto un bel po 'di lavoro su questo 8 anni fa:

È importante poter creare facilmente e in modo efficiente più domini nidificati per mantenere una complessa applicazione Web organizzata e gestibile, rispettando lo spazio dei nomi globale di JavaScript (prevenendo l'inquinamento dello spazio dei nomi) e non rovinando oggetti esistenti nel percorso del namespace mentre si fa .

Da quanto sopra, questa era la mia soluzione del 2008 circa:

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;
};

Questo non sta creando uno spazio dei nomi, ma fornisce una funzione per la creazione di spazi dei nomi.

Questo può essere condensato in un rivestimento singolo minorato:

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};

Esempio di utilizzo:

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

O, come una dichiarazione:

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

O viene quindi eseguito come:

com.example.namespace.test();

Se non hai bisogno di supporto per i browser legacy, una versione aggiornata:

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

Ora, sarei lieto di esporre lo namespace dei namespace al namespace globale stesso. (Peccato che il linguaggio di base non fornisca questo per noi!) Quindi in genere lo userei io stesso in una chiusura, come ad esempio:

(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 un'applicazione più grande, questo deve essere definito solo una volta all'inizio del caricamento di una pagina (per le app Web basate sul client). I file aggiuntivi possono quindi riutilizzare la funzione namespace se mantenuta (inclusa come "opzionale" in precedenza). Nel peggiore dei casi, se questa funzione viene riaffermata alcune volte, sono solo alcune righe di codice e meno se miniate.


Un altro modo per farlo, che considero un po 'meno restrittivo della forma letterale dell'oggetto, è questo:

var ns = new function() {

    var internalFunction = function() {

    };

    this.publicFunction = function() {

    };
};

Quanto sopra è simile al modello del modulo e se ti piace o no , ti permette di esporre tutte le tue funzioni come pubbliche, evitando la rigida struttura di un oggetto letterale.


Possiamo usarlo indipendentemente in questo modo:

var A = A|| {};
A.B = {};

A.B = {
    itemOne: null,
    itemTwo: null,
};

A.B.itemOne = function () {
    //..
}

A.B.itemTwo = function () {
    //..
}

Se usi un Makefile puoi farlo.

// prelude.hjs
billy = new (
    function moduleWrapper () {
    const exports = this;

// postlude.hjs
return exports;
})();

// someinternalfile.js
function bob () { console.log('hi'); }
exports.bob = bob;

// clientfile.js
billy.bob();

Preferisco comunque utilizzare un Makefile una volta arrivato a circa 1000 righe, perché posso effettivamente commentare grandi file di codice rimuovendo una singola riga nel makefile. Rende facile trafficare con le cose. Inoltre, con questa tecnica lo spazio dei nomi appare solo una volta nel preludio, quindi è facile da cambiare e non devi continuare a ripeterlo all'interno del codice della libreria.

Uno script di shell per lo sviluppo live nel browser quando si utilizza un makefile:

while (true); do make; sleep 1; done

Aggiungilo come un'attività make "vai" e puoi "andare avanti" per mantenere aggiornata la tua build mentre esegui il codice.


In JavaScript non ci sono metodi predefiniti per utilizzare gli spazi dei nomi. In JavaScript dobbiamo creare i nostri metodi per definire NameSpaces. Ecco una procedura che seguiamo nelle tecnologie di Oodles.

Registra un NameSpace Di seguito è riportata la funzione per registrare uno spazio dei nomi

//Register NameSpaces Function
function registerNS(args){
 var nameSpaceParts = args.split(".");
 var root = window;

 for(var i=0; i < nameSpaceParts.length; i++)
 {
  if(typeof root[nameSpaceParts[i]] == "undefined")
   root[nameSpaceParts[i]] = new Object();

  root = root[nameSpaceParts[i]];
 }
}

Per registrare un Namespace basta chiamare la funzione sopra riportata con l'argomento come spazio dei nomi separato da '.'(punto). Per esempio Lascia che il nome della tua applicazione sia grande. Puoi creare uno spazio dei nomi seguendo il metodo

registerNS("oodles.HomeUtilities");
registerNS("oodles.GlobalUtilities");
var $OHU = oodles.HomeUtilities;
var $OGU = oodles.GlobalUtilities;

Fondamentalmente creerà la tua struttura NameSpaces come sotto nel backend:

var oodles = {
    "HomeUtilities": {},
    "GlobalUtilities": {}
};

Nella funzione precedente hai registrato uno spazio dei nomi chiamato "oodles.HomeUtilities"e "oodles.GlobalUtilities". Per chiamare questi spazi dei nomi creiamo una variabile cioè var $OHUe var $OGU.

Queste variabili non sono altro che un alias per Intializzare lo spazio dei nomi. Ora, ogni volta che dichiari una funzione che ti appartiene HomeUtilities, la dichiarerai come segue:

$OHU.initialization = function(){
    //Your Code Here
};

Sopra è l'inizializzazione del nome della funzione e viene inserita in uno spazio dei nomi $OHU. e chiamare questa funzione ovunque nei file di script. Basta usare il seguente codice.

$OHU.initialization();

Allo stesso modo, con l'altro NameSpaces.

Spero che sia d'aiuto.


La mia abitudine è di utilizzare la funzione myName () come proprietà di archiviazione, e quindi var myName come titolare del "metodo" ...

Che questo sia abbastanza legittimo o no, bastonami! Mi affido sempre alla mia logica PHP, e le cose funzionano semplicemente. : D

function myObj() {
    this.prop1 = 1;
    this.prop2 = 2;
    this.prop3 = 'string';
}

var myObj = (
 (myObj instanceof Function !== false)
 ? Object.create({

     $props: new myObj(),
     fName1: function() { /* code..  */ },
     fName2: function() { /* code ...*/ }
 })
 : console.log('Object creation failed!')
);

if (this !== that) myObj.fName1(); else myObj.fName2();

Puoi anche farlo in un modo 'viceversa' per verificare prima della creazione dell'oggetto che è molto meglio :

function myObj() {
    this.prop1 = 1;
    this.prop2 = 2;
    this.prop3 = 'string';
}

var myObj = (
    (typeof(myObj) !== "function" || myObj instanceof Function === false)
    ? new Boolean()
    : Object.create({
        $props: new myObj(),
        init: function () { return; },
        fName1: function() { /* code..  */ },
        fName2: function() { /* code ...*/ }
    })
);

if (myObj instanceof Boolean) {
    Object.freeze(myObj);
    console.log('myObj failed!');
    debugger;
}
else
    myObj.init();

Riferimento a questo: JavaScript: creazione di oggetti con Object.create ()





javascript-namespaces