Roadster: Verständnisfrage zur Kapselung

Hallo miteinander!

Wenn ich innerhalb einer Funktion in JS eine Variable mit var deklariere, dann gilt diese Variable nur innerhalb der Funktion.

Aber wie verhält es sich mit Funktionsnamen?

Also zum Beispiel...

function addition( a, b ) {  
  
  var checkA = isNaN( a ), checkB = isNaN( b );  
  
  if (( checkA !== true ) && ( checkB !== true )) {  
  
    var result = getSum( a, b );  
  
  
    function getSum( numA, numB ) {  
  
      var sum = numA + numB;  
  
      return sum;  
  
    }  
  
  
    return result;  
  
  }  
  
}

...wäre dann hier die Funktion getSum() auf den Namesraum der Funktion addition() begrenzt? Aufrufen könnte man diese Funktion von außerhalb der Elternfunktion zwar nicht, aber könnte es nicht trotzdem unter Umständen zu Konfusionen führen, gleiche Funktionsnamen innerhalb eines Scripts zu verwenden, oder wäre das auf die Art tatsächlich ausgeschlossen? - Ich meine, Browser machen ja zuweilen eigenwillige Sachen... ;)

Gruß,

Roadster.

  1. Lieber Roadster,

    ...wäre dann hier die Funktion getSum() auf den Namesraum der Funktion addition() begrenzt?

    ja.

    Aufrufen könnte man diese Funktion von außerhalb der Elternfunktion zwar nicht,

    Richtig.

    aber könnte es nicht trotzdem unter Umständen zu Konfusionen führen, gleiche Funktionsnamen innerhalb eines Scripts zu verwenden, oder wäre das auf die Art tatsächlich ausgeschlossen?

    Wenn im darüberliegenden Scope eine gleichlautende Funktion definiert wurde, dann gilt bei der Notation des Funktionsnamens die im inneren Scope definierte Funktion:

    function test () {  
      
        var a;  
      
        function middle () {  
      
            a = 7; // changes a inside test()  
      
            function inner () {  
      
                var a;  
      
                a = 9; // local a  
      
                function test () {  
                    a = 100;  
                }  
      
                // call "test" inside "inner"  
                test(); // changes a inside inner to 100  
      
                // call "test" outside "inner" and "middle2"  
                window.test();  
            }  
        }  
      
        function middle2 () {  
      
            var a = 9; // local a  
      
            function middle () {  
      
                a = 13; // changes a inside middle2()  
            }  
      
            // call "middle"  
            middle(); // changes a inside middle2() to 13  
        }  
      
        a = 3; // change a inside test() to 3  
    }
    

    Es gibt zwei Funktionen namens "middle", eine im Scope von test() und eine im Scope von middle2. Innerhalb von middle2 war eigentlich die Funktion middle aus dem Scope von test schon bekannt, es wird aber eine "lokale" Funktion gleichen Namens angelegt, so dass der anschließende Aufruf "middle()" nun diese lokale Funktion ausführt.

    Bei "test" ist es noch klarer: Die äußere Funktion ist im Scope des window-Objektes definiert (default), daher kann sie mit window.test() aufgerufen werden. Die gleichnamige Funktion innerhalb von "inner" ist nur dort verfügbar.

    • Ich meine, Browser machen ja zuweilen eigenwillige Sachen... ;)

    Die JavaScript-Engines halten sich sehr gut an die in ECMA-Script standardisierten Sachen, wenn es um diese grundlegenden Sprachkonstrukte geht. Mit den verfügbaren Objekten (in anderen Sprachen auch "Klassen" genannt) ist das etwas anderes wie z.B. document.all und dergleichen...

    Liebe Grüße,

    Felix Riesterer.

    --
    "Wäre die EU ein Staat, der die Aufnahme in die EU beantragen würde, müsste der Antrag zurückgewiesen werden - aus Mangel an demokratischer Substanz." (Martin Schulz, Präsident des EU-Parlamentes)
    1. Hallo Felix,

      vielen Dank für die anschaulichen Erläuterungen!

      Glaube jetzt hab ich's. ;)

      Gruß,

      Roadster.

    2. Hakuna matata!

      Die JavaScript-Engines halten sich sehr gut an die in ECMA-Script standardisierten Sachen, wenn es um diese grundlegenden Sprachkonstrukte geht.

      Naja, die modernen JavaScript-Engines versuchen ihrer Zeit voraus zu sein und implementieren deshalb einen wilden Mix aus EcmaScript 5.1, EcmaScript 6 und sogar EcmaScript 7. Und aus praktischen Gründen implementieren sie auch ihre eigenen Syntax-Erweiterungen. Beispielsweise ist das folgende Snippet, das in ähnlicher Form auch im Beispielcode des OP vorkommt, keine gültige EcmaScript 5.1 Syntax:

      if ( true ) {  
         function foo () {} // Das hier ist eine function declaration, kein function expression  
      }
      

      Es ist aber ein de-facto-Standard unter Javascript-Engines, function declarations als statements zu implementieren, deswegen wird der gezeigte Code auch überall funktionieren. Die gute Nachricht ist, dass die Implementationen sich hier auch ohne offiziellen Standard alle gleich verhalten, weshalb man solchen Code auch beruhigt schreiben kann.

      Wen das Thema interessiert, Juriy Zaytsev hat die Erbsen mal gezählt.

      --
      “All right, then, I'll go to hell.” – Huck Finn
      1. Hakuna matata!

        Die gute Nachricht ist, dass die Implementationen sich hier auch ohne offiziellen Standard alle gleich verhalten, weshalb man solchen Code auch beruhigt schreiben kann.

        Was ist nur los mit mir? Die gute Nachricht ist schlicht weg unwahr, wie man auch unter dem Link nachlesen kann, den ich dazu gepostet habe. Zeit für mich eine Pause zu machen.

        --
        “All right, then, I'll go to hell.” – Huck Finn
  2. Tach!

    Wenn ich innerhalb einer Funktion in JS eine Variable mit var deklariere, dann gilt diese Variable nur innerhalb der Funktion.
    Aber wie verhält es sich mit Funktionsnamen?

    Ebenso.

    ...wäre dann hier die Funktion getSum() auf den Namesraum der Funktion addition() begrenzt?

    Ja.

    Aufrufen könnte man diese Funktion von außerhalb der Elternfunktion zwar nicht, aber könnte es nicht trotzdem unter Umständen zu Konfusionen führen, gleiche Funktionsnamen innerhalb eines Scripts zu verwenden, oder wäre das auf die Art tatsächlich ausgeschlossen?

    Nicht nur bei Funktionen, auch bei Bezeichnern für Variablen gibts eine Reihenfolge, wo diese gesucht werden: zuerst im aktuellen Scope, dann im Scope oben drüber und so weiter. Gleichnamige Bezeichner können verwirren, müssen es aber nicht per se. Kommt auch drauf an, wie übersichtlich die zu betrachtende Codestelle ist.

    dedlfix.

    1. Hallo dedlfix,

      auch dir vielen Dank!

      Bin davon ausgegangen, dasses so laufen müsste, aber war mir halt nicht sicher. ;)

      Gruß,

      Roadster.