web-dev-qa-db-fra.com

comprendre l'espace de noms global et les fermetures javascript

J'essaie d'améliorer ma compréhension de l'espace de noms global en javascript et je suis curieux de certaines choses:

  1. existe-t-il un objet "DIEU" (c'est-à-dire un parent) auquel tous les objets (puisque toutes les choses sauf les primitives sont des objets) doivent répondre et si oui, cet objet serait-il une "fenêtre"?

  2. pourquoi est-ce une mauvaise idée d'avoir des vars/fonctions au niveau global?

  3. si c'est vraiment une mauvaise idée d'avoir des vars/fonctions de portée mondiale, les fermetures seraient-elles le meilleur moyen d'éviter cela? exemple:

    function parent(){
        var x = 'some value';//this var would be considered global to all children functions but not in the true global namespace
        function child1(){
            x.someMethod()
        } 
        function child2(){
            x*something;
        }
        function child3(){
            x+=something;
            child2()
            child1()
        }
        child3()
    }
    parent()
    
31
zero
  1. Existe-t-il un dieu (c'est-à-dire un parent) objet?

    Oui. Plus techniquement, c'est l'objet global dont toutes ces primitives sont membres; il se trouve que dans le navigateur, l'objet window est l'objet global.

    > window.String === String;
    true
    
  2. Pourquoi est-ce une mauvaise idée d'avoir des vars/fonctions au niveau mondial?

    Parce que si vous ajoutez de nombreuses bibliothèques/scripts tiers, ils partagent tous le même objet global, il y a un risque de collision de noms. C'est un vrai problème avec toutes les bibliothèques qui utilisent $ Comme alias (jQuery, Prototype et plus).

  3. Si c'est vraiment une mauvaise idée d'avoir des vars/fonctions à portée mondiale, les fermetures seraient-elles le meilleur moyen d'éviter cela?

    x ne doit pas être considéré comme global. Cela fait partie de la fermeture formée en déclarant les fonctions enfants à l'intérieur de la fonction parent(). Le problème de votre extrait de code est que parent() est global; que se passe-t-il si un autre code re-déclaré parent()? Ce serait mieux:

    (function () {
    
    function parent(){
        var x = 'some value';
        function child1(){
            x.someMethod()
        } 
        function child2(){
            x*something;
        }
        function child3(){
            x+=something;
            child2()
            child1()
        }
        child3()
    }
    parent()
    
    }());
    

    Le fait que x est accessible dans les fonctions enfants n'est pas mauvais; vous devriez avoir écrit ces fonctions vous-même, vous devez donc être conscient de l'existence de x. Gardez à l'esprit que si vous re-déclarez x dans ces fonctions enfant avec var, vous n'affecterez pas le x dans parent().

26
Matt
  1. Oui, dans un environnement de navigateur, "l'objet divin" est une fenêtre. Il est généralement appelé l'objet global , pas l'objet divin cependant;) dans environnements sans navigateur tels que nodejs, l'objet global peut utiliser un autre nom que window.

  2. Si vous mettez tout en tant que globaux, vous risquez de rencontrer des noms en collision. Il y a aussi la question de encapsulation - en d'autres termes, en ne mettant les variables que dans la portée où cela est nécessaire, votre code est généralement mieux loti.

  3. Oui, c'est à peu près l'approche préférée. Vous pouvez également utiliser IIFE

5
Jani Hartikainen
  1. Pour autant que je sache, je dirais que oui, la fenêtre est l'objet parent. Cependant, à l'intérieur d'un Iframe, vous avez votre propre objet window, distinct de la fenêtre environnante à laquelle vous pouvez accéder via window.parent

  2. C'est une mauvaise idée d'avoir BEAUCOUP de var global à cause d'une collision de noms potentielle et donc difficile de détecter les bugs. En général, il est plus sûr de concevoir un espace de noms (voir le $ de jQuery, etc.) et modulariser le code.

  3. Attention, parent est un champ de fenêtre potentiel existant. Ces fonctions prises à part sont des objets donc la même observation qu'en 2) s'applique ici.

3
Nicocube

Si vous AVEZ BESOIN DE pour placer des variables dans l'espace de noms global, et vous le ferez probablement à un moment donné, créez une variable d'objet unique et ajoutez-y vos autres variables en tant que propriétés ou méthodes. Donnez à l'objet un nom qui ne sera probablement pas utilisé par quelqu'un d'autre (certes, c'est là que les problèmes de collision surviennent, mais qui peuvent être atténués par une dénomination prudente et standardisée).

par exemple. Au lieu de:

var thing1 = 'table';
var anotherthing = 'chair';
var mypet = 'dog';
var count = 4;
var show_something: function( _txt ) { return _txt.trim(); };

Faites ceci:

var cmjaimet_obj = {
  thing1: 'table',
  anotherthing: 'chair',
  mypet: 'dog',
  count: 4,
  show_something: function( _txt ) { return _txt.trim(); }
};

Ensuite, appelez-les plus tard en tant que propriétés:

par exemple. Au lieu de:

count += 2;
anotherthing = 'sofa';
console.log( show_something( 'Thing: ' + anotherthing ) );

Faites ceci:

cmjaimet_obj.count += 2;
cmjaimet_obj.anotherthing = 'sofa';
console.log( cmjaimet_obj.show_something( 'Thing: ' + cmjaimet_obj.anotherthing ) );
3
Charles Jaimet