Question Comment puis-je déclarer un espace de noms en JavaScript?


Comment créer un espace de noms en JavaScript afin que mes objets et fonctions ne soient pas écrasés par d'autres objets et fonctions du même nom? J'ai utilisé ce qui suit:

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

Y a-t-il une façon plus élégante ou plus succincte de le faire?


919
2018-05-19 08:11


origine


Réponses:


J'aime ça:

var yourNamespace = {

    foo: function() {
    },

    bar: function() {
    }
};

...

yourNamespace.foo();

713
2018-05-19 08:22



j'utilise l'approche trouvée sur le site Enterprise jQuery:

Voici leur exemple montrant comment déclarer les propriétés et fonctions privées et publiques. Tout est fait comme une fonction anonyme auto-exécutable.

(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 ));

Donc, si vous voulez accéder à l'un des membres du public, vous allez juste aller skillet.fry() ou skillet.ingredients.

Ce qui est vraiment cool, c'est que vous pouvez maintenant étendre l'espace de noms en utilisant exactement la même syntaxe.

//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 ));

Le troisième undefined argument

Le troisième, undefined argument est la source de la variable de la valeur undefined. Je ne sais pas si c'est encore pertinent aujourd'hui, mais tout en travaillant avec les anciens navigateurs / JavaScript standards (ecmascript 5, javascript <1.8.5 ~ firefox 4), la variable globale-scope undefined est accessible en écriture, donc n'importe qui pourrait réécrire sa valeur. Le troisième argument (lorsqu'il n'est pas passé une valeur) crée une variable nommée undefined qui est limité à l'espace de noms / fonction. Comme aucune valeur n'a été transmise lors de la création de l'espace de nom, la valeur par défaut est la valeur undefined.


1015
2018-05-10 08:28



Une autre façon de le faire, que je considère comme un peu moins restrictive que la forme littérale de l'objet, est la suivante:

var ns = new function() {

    var internalFunction = function() {

    };

    this.publicFunction = function() {

    };
};

Ce qui précède est à peu près comme le motif de module et Que cela vous plaise ou non, il vous permet d'exposer toutes vos fonctions comme publiques, tout en évitant la structure rigide d'un objet littéral.


334
2018-05-19 08:39



Y a-t-il une façon plus élégante ou plus succincte de le faire?

Oui. Par exemple:

var your_namespace = your_namespace || {};

alors vous pouvez avoir

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

154
2018-05-26 11:34



Je le construis normalement dans une fermeture:

var MYNS = MYNS || {};

MYNS.subns = (function() {

    function privateMethod() {
        // Do private stuff, or build internal.
        return "Message";
    }

    return {
        someProperty: 'prop value',
        publicMethod: function() {
            return privateMethod() + " stuff";
        }
    };
})();

Mon style au fil des ans a subtilement changé depuis que j'ai écrit ceci, et je me retrouve maintenant à écrire la fermeture comme ceci:

var MYNS = MYNS || {};

MYNS.subns = (function() {
    var internalState = "Message";

    var privateMethod = function() {
        // Do private stuff, or build internal.
        return internalState;
    };
    var publicMethod = function() {
        return privateMethod() + " stuff";
    };

    return {
        someProperty: 'prop value',
        publicMethod: publicMethod
    };
})();

De cette façon, je trouve l'API publique et la mise en œuvre plus facile à comprendre. Considérez l'instruction return comme étant une interface publique à l'implémentation.


88
2018-05-20 20:07



Parce que vous pouvez écrire différents fichiers de JavaScript et plus tard les combiner ou ne pas les combiner dans une application, chacun doit être capable de récupérer ou de construire l'objet espace de noms sans endommager le travail des autres fichiers ...

Un fichier pourrait avoir l'intention d'utiliser l'espace de noms namespace.namespace1:

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

namespace.namespace1.doSomeThing = function(){}

Un autre fichier pourrait vouloir utiliser l'espace de noms namespace.namespace2:

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

namespace.namespace2.doSomeThing = function(){}

Ces deux fichiers peuvent vivre ensemble ou séparément sans entrer en collision.


55
2017-11-09 04:27



Voici comment Stoyan Stefanov le fait dans son Patterns JavaScript livre que j'ai trouvé très bon (il montre aussi comment il fait des commentaires qui permettent la documentation de l'API générée automatiquement, et comment ajouter une méthode au prototype d'un objet personnalisé):

/**
* My JavaScript application
*
* @module myapp
*/

/** @namespace Namespace for MYAPP classes and functions. */
var MYAPP = MYAPP || {};

/**
* A maths utility
* @namespace MYAPP
* @class math_stuff
*/
MYAPP.math_stuff = {

    /**
    * Sums two numbers
    *
    * @method sum
    * @param {Number} a First number
    * @param {Number} b Second number
    * @return {Number} Sum of the inputs
    */
    sum: function (a, b) {
        return a + b;
    },

    /**
    * Multiplies two numbers
    *
    * @method multi
    * @param {Number} a First number
    * @param {Number} b Second number
    * @return {Number} The inputs multiplied
    */
    multi: function (a, b) {
        return a * b;
    }
};

/**
* Constructs Person objects
* @class Person
* @constructor
* @namespace MYAPP
* @param {String} First name
* @param {String} Last name
*/
MYAPP.Person = function (first, last) {

    /**
    * First name of the Person
    * @property first_name
    * @type String
    */
    this.first_name = first;

    /**
    * Last name of the Person
    * @property last_name
    * @type String
    */
    this.last_name = last;
};

/**
* Return Person's full name
*
* @method getName
* @return {String} First name + last name
*/
MYAPP.Person.prototype.getName = function () {
    return this.first_name + ' ' + this.last_name;
};

46
2018-04-22 15:44



J'utilise cette approche:

var myNamespace = {}
myNamespace._construct = function()
{
    var staticVariable = "This is available to all functions created here"

    function MyClass()
    {
       // Depending on the class, we may build all the classes here
       this.publicMethod = function()
       {
          //Do stuff
       }
    }

    // Alternatively, we may use a prototype.
    MyClass.prototype.altPublicMethod = function()
    {
        //Do stuff
    }

    function privateStuff()
    {
    }

    function publicStuff()
    {
       // Code that may call other public and private functions
    }

    // List of things to place publically
    this.publicStuff = publicStuff
    this.MyClass = MyClass
}
myNamespace._construct()

// The following may or may not be in another file
myNamespace.subName = {}
myNamespace.subName._construct = function()
{
   // Build namespace
}
myNamespace.subName._construct()

Le code externe peut alors être:

var myClass = new myNamespace.MyClass();
var myOtherClass = new myNamepace.subName.SomeOtherClass();
myNamespace.subName.publicOtherStuff(someParameter);

32
2018-05-19 08:26



Ceci est une suite du lien de l'utilisateur106826 vers Namespace.js. Il semble que le projet a déménagé GitHub. C'est maintenant smith / namespacedotjs.

J'ai utilisé cette simple aide JavaScript pour mon petit projet et jusqu'à présent, il semble être assez léger et polyvalent pour gérer les espaces de noms. et chargement des modules / classes. Ce serait génial si cela me permettait d'importer un paquet dans un espace de noms de mon choix, et pas seulement dans l'espace de noms global ... soupir, mais c'est à part ça.

Il vous permet de déclarer l'espace de noms puis de définir des objets / modules dans cet espace de noms:

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

Une autre option consiste à déclarer l'espace de noms et son contenu à la fois:

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

Pour plus d'exemples d'utilisation, regardez le fichier example.js dans la source.


32
2017-08-27 23:15



Échantillon:

var namespace = {};
namespace.module1 = (function(){

    var self = {};
    self.initialized = false;

    self.init = function(){
        setTimeout(self.onTimeout, 1000)
    };

    self.onTimeout = function(){
        alert('onTimeout')
        self.initialized = true;
    };

    self.init(); /* If it needs to auto-initialize, */
    /* You can also call 'namespace.module1.init();' from outside the module. */
    return self;
})()

Vous pouvez éventuellement déclarer un local variable, same, comme self et assigner local.onTimeout si vous voulez que ce soit privé.


29
2018-05-10 11:44



Vous pouvez déclarer une fonction simple pour fournir des espaces de noms.

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

13
2018-04-28 14:03