Toni Faber: Variablen im globalen Namensraum

Variablen im globalen Namensraum
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

Hi,

Ich stoße immer wieder auf Situationen, in denen ich immer wieder mal eine Funktion aufrufe, in der ich dann (neben anderen Aktionen) z.B. eine Variable inkrementieren will.

Definiere ich diese Variable innerhalb der Funktion, so wird sie bei jedem Funktionsaufruf neu initialisiert, was ja nicht Ziel der Übung ist.

...daher sehe ich als letzte Konsequenz eigentlich nur mehr die Option, mit der Variable den globalen Namensraum zu verschmutzen, was in allerletzter (versprochen) Konsequenz zu einer Aggregation (scheinbar) herrenloser Variablen führt, nach dem Schema:

let ichBinEineVariableUndSTOLZdarauf;
let ichBinEineVariableUndNOCHstolzer = 0;
let ichBinEineVariableUndMirReichtDerDrittePlatz;
let ichBinEineVariableDerLangsamDieNamenAusgehen;
let wasSollIchErstSagenIchWurdeNACHdirDefiniert = {};
let NICHTjammern;
// ...

Gibt's da irgendwelche Strategien, diese Auswüchse im globalen Namensraum zu vermeiden?

LG, Toni

  1. Tach!

    Gibt's da irgendwelche Strategien, diese Auswüchse im globalen Namensraum zu vermeiden?

    Ja, einen Block erstellen.

    {
        let i = 0;
        function foo() {
            return i++;
        }
    }
    
    console.log(foo());
    console.log(foo());
    console.log(foo());
    
    

    Somit sitzt nur die Funktion im globalen Namensraum. Eine moderne Alternative ist außerdem Module.

    m.js:

    let i = 0;
    function foo() {
        return i++;
    }
    module.exports = foo;
    

    woanders.js:

    const foo = require('./m');
    
    console.log(foo());
    console.log(foo());
    console.log(foo());
    

    dedlfix.

    1. Großer Dank und Anerkennung.

  2. Hallo Toni,

    das Modulkonzept ist im Normalfall die sinnvollste Lösung.

    Aber schon mal braucht man tatsächlich was Globales, und dann hilft ein einziges globales Objekt weiter. Darin legt man die "Variablen", die man braucht, als Propertys an. Zusammen mit dem Block-Konstrukt kann man noch ein paar private Helper hinzufügen.

    <script>
    {
       let zähler = 0;    // let: nur im Block sichtbar (IE ab Version 11)
       Toni = {           // ohne var/let: globalgalaktisch
          stolzeVariable: 1,
          eitleVariable: 42,
          heulsuse: 99,
          getNextValue: function() { return ++zähler; };
          nochEinWert: () => ++zähler;
          get neuerWert() { return ++zähler; }
       };
    }
    
    let a = Toni.getNextValue(); // 1
    let b = Toni.nochEinWert();  // 2
    let c = Toni.neuerWert;      // 3
    </script>
    

    Hier siehst Du auch drei Möglichkeiten, Funktionen an ein Objekt zu binden (also Methoden).

    • Als function - die klassische Art, klappte schon 2005 oder früher
    • Als Arrow-Funktion - nicht im Internet Explorer
    • als Property-Getter - klappt in Chrome, Fuchs und sogar im Internet Explorer ab Version 9

    Wenn Du den Internet Explorer vor Version 11 unterstützen musst/willst, ist das Blockkonzept aber untauglich. Module gibt's dann auch nicht. Aber IIFE - immediately executed function expression. Siehe Self-Wiki.

    Rolf

    --
    sumpsi - posui - obstruxi