Les namespaces

Parent Previous Next



Les namespaces



En informatique, un namespace, ou « espace de nom » en français, est un ensemble fictif qui contient des informations, généralement des propriétés et des méthodes, ainsi que des sous-namespaces. Le but d'un namespace est de s'assurer de l'unicité des informations qu'il contient.


Par exemple, Sébastien et Johann habitent tous deux au numéro 42. Sébastien dans la rue de Belgique et Johann dans la rue de France. Les numéros de leurs maisons peuvent être confondus, puisqu'il s'agit du même. Ainsi, si Johann dit « J'habite au numéro 42 », c'est ambigu, car Sébastien aussi. Alors, pour différencier les deux numéros, nous allons toujours donner le nom de la rue. Ce nom de rue peut être vu comme un namespace : il permet de différencier deux données identiques.


En programmation, quelque chose d'analogue peut se produire : imaginez que vous développiez une fonction myBestFunction(), et vous trouvez un script tout fait pour réaliser un effet quelconque. Vous ajoutez alors ce script au vôtre. Problème : dans ce script tout fait, une fonction myBestFunction() est aussi présente… Votre fonction se retrouve écrasée par l'autre, et votre script ne fonctionnera plus correctement.


Pour éviter ce genre de désagrément, nous allons utiliser un namespace !


Le Javascript, au contraire de langages comme le C# ou le Java, ne propose pas de vrai système de namespace. Ce que l'on étudie ici est un système pour reproduire plus ou moins correctement un tel système.


Définir un namespace


Un namespace est une sorte de catégorie : vous allez vous créer un namespace, et, au sein de celui-ci, vous allez placer vos fonctions. De cette manière, vos fonctions seront en quelque sorte préservées d'éventuels écrasements. Comme le Javascript ne gère pas nativement les namespaces (comprenez : il n'y a pas de structure consacrée à cela), nous allons devoir nous débrouiller seuls, et utiliser un simple objet littéral. Premier exemple :

var myNamespace = {

    myBestFunction: function() {

        alert('Ma meilleure fonction !');

    }

};

 

// On exécute la fonction :

myNamespace.myBestFunction();


On commence par créer un objet littéral appelé myNamespace. Ensuite on définit une méthode :myBestFunction(). Souvenez-vous, dans le chapitre sur les objets littéraux, nous avions vu que nous pouvions définir des propriétés, et il est aussi possible de définir des méthodes, en utilisant la même syntaxe.


Pour appeler myBestFunction(), il faut obligatoirement passer par l'objet myNamespace, ce qui limite très fortement la probabilité de voir votre fonction écrasée par une autre. Bien évidemment, votre namespace doit être original pour être certain qu'un autre développeur n'utilise pas le même… Cette technique n'est donc pas infaillible, mais réduit considérablement les problèmes.


Un style de code


Utiliser un namespace est aussi élégant, car cela permet d'avoir un code visuellement propre et structuré. Une grande majorité des « gros » scripts sont organisés via un namespace, notamment car il est possible de décomposer le script en catégories. Par exemple, vous faites un script qui gère un webmail (comme Hotmail ou GMail) :

var thundersebWebMail = {

    // Propriétés

    version: 1.42,

    lang: 'english',

 

    // Initialisation

    init : function() { /* initialisation */ },

 

    // Gestion des mails

    mails: {

        list: function() { /* affiche la liste des mails */ },

        show: function() { /* affiche un mail */ },

        trash: function() { /* supprime un mail */ },

        // et cætera…

    },

 

    // Gestion des contacts

    contacts: {

        list: function() { /* affiche la liste des contacts */ },

        edit: function() { /* édite un contact */ },

        // et cætera…

    }

};


Ce code fictif comprend une méthode d'initialisation et deux sous-namespaces : mails et contacts, servant respectivement à gérer les e-mails et les contacts. Chacun de ces sous-namespaces contient les méthodes qui lui sont propres.


Structurer son code de cette manière est propre et lisible, ce qui n'est pas toujours le cas d'une succession de fonctions. Voici l'exemple que nous venons de voir mais cette fois-ci sans namespaces :

var webmailVersion = 1.42,

    webmailLang    = 'english';

 

function webmailInit() { /* initialisation */ }

 

function webmailMailsList() { /* affiche la liste des mails */ }

function webmailMailsShow() { /* affiche un mail */ }

function webmailMailsTrash() { /* supprime un mail */ }

 

function webmailContactsList() { /* affiche la liste des contacts */ }

function webmailContactsEdit() { /* édite un contact */ }

C'est tout de suite plus confus, il n'y a pas de hiérarchie, c'est brouillon. Bien évidemment, cela dépend du codeur : un code en namespace peut être brouillon, alors qu'un code « normal » peut être très propre ; mais de manière générale, un code en namespace est accessible, plus lisible et plus compréhensible. C'est évidemment une question d'habitude.


L'emploi de this


Le mot-clé this s'utilise ici exactement comme dans les objets vus précédemment. Mais attention, si vous utilisez this dans un sous-namespace, celui-ci pointera vers ce sous-namespace, et non vers le namespace parent. Ainsi, l'exemple suivant ne fonctionnera pas correctement, car en appelant la méthodeinit() on lui demande d'exécuter this.test(). Or, this pointe vers subNamespace, et il n'existe aucune méthode test() au sein de subNamespace.

var myNamespace = {

 

    test: function() { alert('Test'); },

 

    subNamespace: {

        init: function() {

            this.test();

        }

    }

 

};

 

myNamespace.subNamespace.init();


Pour accéder à l'objet parent, il n'y a malheureusement pas de solution si ce n'est écrire son nom entièrement :

var myNamespace = {

 

    test: function() { alert('Test'); },

 

    subNamespace: {

        init: function() {

            myNamespace.test();

        }

    }

 

};

 

myNamespace.subNamespace.init();


Vérifier l'unicité du namespace


Une sécurité supplémentaire est de vérifier l'existence du namespace : s'il n'existe pas, on le définit et dans le cas contraire, on ne fait rien pour ne pas risquer d'écraser une version déjà existante, tout en retournant un message d'erreur.

// On vérifie l'existence de l'objet myNamespace

if (typeof myNamespace === 'undefined') {

 

    var myNamespace = {

        // Tout le code

    };

 

} else {

    alert('myNamespace existe déjà !');

}


Créé avec HelpNDoc Personal Edition: Générateur d'aide complet

Site à deux balles