Schnelleinstieg (Funktionen)

ECMAScript hat einen modernen Mechanismus für die Implementierung von Funktionen (Function.prototyp). Jeder Funktion entspricht auch zugehöriges Objekt, das zum (versteckten) Funktionskontext gehört. Funktionen können in Variablen, Objekten, Array's gespeichert werden und als Argument an Funktionen übergeben werden.
Hier sind einige seiteninterne Anspring-Links für Quick: Namespace-Konzept Quick: Globales in Bibliothek
Im einzelnen Eingebaute Funktionen Funktionen selbstgeschrieben globale Funktionssammlung eine Bibliothek erstellen Erklaerungen und Aufrufkaskaden

Welche eingebaute Funktionen gibt es?

Zu ECMAScript gehören bereits 'build in functions' (Function-Prototyp, global). Zu Funktionen gehören i.a. Argumente. Der Begriff "Argument" wird oft mit "aktuelles Argument" oder "formaler Parameter" gleich gesetzt. Es gibt globale ECMAScript-Funktionen, wie z.B.

 escape(),      unescape(),  
 parseInt(),    parseFloat(), 
 eval()

Es gibt eingebaute String-Funktionen, die unter dem String-Prototyp hinterlegt sind, wie z.B.

.charAt(pos),             
.charCodeAt(pos),          .fromCharCode(zeichen...),
.indexOf(suchstring, pos), .lastIndexOf(suchstring,pos),
.match(re),                .search(re), 
.replace(suchwert, ersetzungswert),
.slice(anfang, ende),      .substr(), 
.split(separator, limit), 
.toLowerCase(),           .toUpperCase(),      .toFixed(), ...            

Es gibt eingebaute mathematische Funktionen, die unter dem Math-Objekt hinterlegt sind, wie z.B.

Math.min(), Math.max(), Math.floor(), Math.ceil(), Math.round()
Math.cos(),  Math.sin(),  Math.tan(), 
Math.acos(), Math.asin(), Math.atan(),
Math.sqrt(), Math.pow(), Math.exp(), Math.random()

Konstanten 
Math.LN2, Math.LN10, Math.LOG2E, Math.LOG10E,
Math.PI,  Math.SQRT1_2, Math.SQRT2     

Es gibt eingebaute Array-Funktionen, die zu dem Object-Prototyp gehören.

.push(), .shift(), .sort(), .split(), .join(), .slice(), .splice()
Wie werden Funktionen selbst geschrieben?

Funktionsobjekte werden mit Funktionsliteralen erzeugt.

function ist ein reserviertes Wort. Eine Funktion ohne den optionalen Namen opt_name wird anonyme Funktion genannt. Parameter (hier a, b) werden innerhalb der Funktion als Variablen definiert und mit dem jeweiligen Aufrufwert initialisiert. Weggelassene Funktion-Aufruf-Parametern werden mit undefined initialisiert. Die Sichtbarkeit von inneren Variablen ist nicht ein Code-Block, sondern stets der Funktionsrumpf.

<script>
function addiere (a, b) { return a + b; }

var add = function opt_name (a, b) {return a + b; };
                       // Semikolon wegen add = ...;
var erg = "addiere(3, 4) liefert " + addiere(3, 4);
    erg += add('\ntypeof addiere  liefert ', typeof addiere );
    erg += add('\ntypeof add      liefert ', typeof add     );
    erg += add("\ntypeof opt_name liefert ", typeof opt_name);

document.write("Ausgabe:<pre>" + erg+'</pre>');
</script>
Wie wird eine globale Funktionssammlung erstellt?

Hier ein (stark vereinfachtes) Beispiel.

<p id="id_p" class="dir"> Betrachte dieses id_p-Tag mit
  <span id="id_span"> id_span </span>
  <dfn  id="id_dfn">  id_dfn  </dfn>
</p>

Ein p-Tag enthalte ein span und ein dfn-Tag mit id='id_p', id='id_span' und id='id_dfn'. Dies sieht dann im Browser so aus:

Mit Hilfe der id-Identifizierer soll auf die zugeordneten HTML-Laufzeit-Elemente (insbesondere .innerHTML) zugegriffen werden. Hierzu die Funktionen get_obj(id), get_string(id) set_string(id, str). Die Funktion tausche(id1, id2) vertauscht den id_span-innerHTML-Content mit dem id_dfn-innerHTML-Content. Mit globalen Funktionen und den globalen Objekten var win = window, doc = win.document; sieht das etwa so aus:

<script>
var win = window, doc = win.document;

function show(str)           { win.alert(str);                }
function get_obj(id)         { return doc.getElementById(id); }
function set_string(id, str) { get_obj(id).innerHTML = str;   }
function get_string(id)      { return get_obj(id).innerHTML;  }
function tausche(id1, id2)   {
     var s1 = get_string(id1), s2 = get_string(id2);
              set_string(id1, s2);  set_string(id2, s1);
}
</script>
<a href="javascript:show(get_string('id_p'))"> zeige </a>
<a href="javascript:tausche('id_dfn','id_span');"> vertausche </a>

Betrachte dieses id_p-Tag mit id_span id_dfn

Teste die globalen Funktionen mit vertausche id_span mit id_dfn Content (.innerHTML) und zeige .innerHTML-String von id_p an

Wie wird eine (Funktions-) Bibliothek erstellt?

Es gibt zahlreiche Möglichkeiten. Hier wird eine robuste Möglichkeit beschrieben, die Funktionen und Daten in einen privaten Bereich kapselt und einen Objekt-Namespace verwendet. Es wird das folgendes Scenario angenommen:

  1. Einige eigene Funktionen werden im globalen Kontext und mit den globalen Daten entwickelt und getestet.
  2. Im globalen Kontext kann jede Funktion diese globalen Werte verwenden.
  3. Im globalen Kontext kann jede Funktion eine andere globale Funktion aufrufen.
  4. Bei HTML-Seiten wird z.B. das globale window-Objekt und (davon abgeleitet) das Dokument-Objekt var doc = window.document; verwendet.
  5. Wie wird nun daraus eine (Funktions-) Bibliothek, die "möglichst alles" in einem privaten Bereich kapselt?
  6. Als Name für den Objekt-Namespace (= erzeugtes Objekt der Methoden) werde dom verwendet.
    • Am Anfang der globalen Funktionssammlung wird das
      var win = window, doc = win.document;
      ersetzt durch
      var dom = (function (win) { var  doc = win.document;
    • Am Ende der globalen Funktionssammlung wird angefügt
      return {show:show, get_obj:get_obj, set_string:set_string, get_string:get_string, tausche:tausche};
      } (window));
      
  7. Anstelle der obigen Aufrufe von globalen Ffunktionen get_obj(id), get_string(id), set_string(id, str) ist nun dom.get_obj(id), dom.get_string(id), dom.set_string(id, str) zu verwenden.
  8. Wie sieht der dom-Code dann aus?
    <script>
    var dom = (function (win) { var doc = win.document;
    
    function show(str)           { win.alert(str);                }
    function get_obj(id)         { return doc.getElementById(id); }
    function set_string(id, str) { get_obj(id).innerHTML = str;   }
    function get_string(id)      { return get_obj(id).innerHTML;  }
    function tausche(id1, id2)   {
         var s1 = get_string(id1), s2 = get_string(id2);
                  set_string(id1, s2);  set_string(id2, s1);
    }
    return {show:show, get_obj:get_obj, set_string:set_string, get_string:get_string, tausche:tausche};
    } (window));
    </script>
    

    Betrachte dieses idp-Tag mit idspan iddfn

    teste: vertausche idspan mit iddfn Content (.innerHTML) und zeige .innerHTML-String von idp an

Erklärungen zu dem dom-Bibliothek-Muster
Aufrufkaskaden

Im inneren, privaten Namespace-Bereich können Variablen verwendet werden, die von den Namespace-Funktionen verwendet werden können. Wenn diese Funktionen jeweils return this zurück geben, so können die Funktionsaufrufe kaskadiert werden. Beim folgenden Beispiel operiert die Funktion-Kaskade dom.push(...).push(...) usw. auf den privaten dom-Daten. Ein Vertauschen erfolgt durch

dom.push('id1').push('id2').pop('id1').pop('id2');

Infolge

return {show:show, push:push, pop:pop};

sind lediglich dom.show(), dom.push(), dom.pop() öffentliche Funktionen.

<script>
var dom = (function (win) { var doc = win.document, arr = [];

function get_obj(id) { return doc.getElementById(id); }

function push(id) { arr.push( get_obj(id).innerHTML ); return dom; }
function pop(id){ get_obj(id).innerHTML = arr.pop(); return dom; }
function show() { win.alert(arr.join()); return dom; }

return {show:show, push:push, pop:pop};
} (window));
</script>

Betrachte dieses p-Tag mit id1 id2

teste: vertausche infolge von dom.push('id1').push('id2').push('id1').push('id2');

teste schrittweise:
dom.push('id1') dom.show()     dom.push('id2') dom.show()
dom.pop('id1') dom.show()     dom.pop('id2') dom.show()