Übungsbeispiele 2 (Klausurvorbereitung, ohne Lösung) Gibt es ECMAScript-Beispiele? ...

Georg Simmel:
"Gebildet ist, wer weiß,
wo er findet,
was er nicht weiß."

Ü: Fragen wie .slice() Array, String

Fragen (Erklärung kann auch anhand von Beispiele erfolgen):

  1. Was bindet bei "Anzahl der Zeichen = " + ' \t\t abcd \t\t '.trim().length stärker:
    a) das + Zeichen zum Verketten der beiden Strings oder
    b) der Punkt beim .trim()-Aufruf?

  2. Was gibt arr.slice(pos) zurück?

  3. Welcher Unterschied besteht zwischen

    str.slice(pos, pos+n) und
    str.substring(pos, pos+n)

  4. Was bewirkt arr.slice(pos, pos+n)?
Ü: str.trim() als "built-in Function" Wie str.trim() programmieren?

Es gibt keine eingebaute Stringfunktion für dastrim-men eines Strings, das am Stringsnfan und am Stringende alle white-Charakter löscht. Wie kann eine solche Funktion geschrieben werden, die die eingebauten Funktionen ergänzt?

<script>
  String._________________.trim = function() { 

     return ________.replace(/___________________/g, '');
  }
</script>
Ü: Umschreiben in "built-in Function" ges.: x.is_method(prop), x.is_collection(prop), x.is_object(prop)

Die folgenden Funktionen sollen so umgeschrieben werden, daß Funktionen im "built-in"-Stil (.prototype.) entstehen. Bitte auch testen.

function is_method(object, property) {
  var t = typeof object[property];  
  return t==='function'|| t==='unknown' || (!!(t==='object' && object[property]));
}

function is_collection(object, property) { var t = typeof object[property];  
  return (!!(t==='object' && object[property])) || t==='function';
}

function is_object(object, property) {
  return !!(typeof(object[property]) === 'object' && object[property]);
}
Ü: Inspektion von dynamischen Objekten debuggen ...

In der Programmierung bedeutet Reflexion (engl. reflection) bzw. Introspektion, dass ein Programm seine eigene Struktur kennt und diese, wenn nötig, modifizieren kann. So kann die CPU den Opcode als Daten betrachten, eine virtuellen Maschine kann zur Laufzeit ergänzende Informationen abzufragen.

Können ergänzende Informationen dynamisch aufgerufen und ggf. Typen und Objekte sogar dynamisch strukturiert werden, so ermöglicht eine solche "Reflexion" eine größere Laufzeitflexibilität (siehe z.B. Reflexion ➹). ECMAScript hat zur Laufzeit die typeof- und hasOwnProperty-Abfragemöglichkeit.

Die (weiter unten) zu ergänzende Funktion myObj.to_string(props) kann für props diejenigen Property-Namen angeben, die angezeigt werden sollen, wie z.B. {a:'A',b:'B','c-test':4711}.to_string(['b','c-test']). Um alle Objekt-Paare anzuzeigen wird das Argument wegelassen, wie z.B. document.body.to_string(). Bitte ergänzen und testen:

  Object.prototype.to_string = function(props) {
  var p, pp, ppp, i, s = "", el = this, name = el.nodeName || ''; 
  props = props || false;
  if (props) { // nur diese properties
    for (i = 0; i < props.length; i += 1) {
      pp = props[i]; ppp = el[pp];
      if (el.hasOwnProperty(pp)) { s += "\n" + _______ + "." + ______ + "=" + ((typeof ________ === 'object') ? 'Element' : ________); }
    }
  } else { // alle properties
    for (p in el) {
      if (el.hasOwnProperty(p)) {
        s += "\n" + name + "." + _____ + "=" + ((typeof ______ === 'object') ? 'Element' : ___________);
      }
    }
  } return s;
}

Durch var s = {a:'A',b:'B','c-test':4711}.to_string(['b','c-test']) wird

s = _________________________________________________________________________________

Ü: Tabellen-Sichten Table-Spalten ein- und ausblenden

Hier geht es um unterschiedliche Präsentationesmöglichkeiten einer HTML-Table. Eine Tabelle kann z.B. aus DB-Daten erstellt und umfangreich sein. Zum Experimentieren soll lediglich die folgende Table betrachtet werden:

<table border="1" id="myTable"><tbody>
<tr><td> Produkte
</td><td> Betriebe 
</td><td> Unsätze 

</td></tr><tr><td> Art-Deko-Steine
</td><td> XQuarz GmbH 
</td><td> 2 712 456.00

</td></tr><tr><td> Frischkäse
</td><td> Hans Schnell, Hintertupfingen
</td><td> 12 456.50

</td></tr><tr><td> Bio-Eier
</td><td> Freiland-AG, Freilichtbergen
</td><td style="text-align:right"> 9 456.99

</td></tr></tbody></table>

Der Betrachter soll mit ECMAScript spezielle Sichten auswählen können.

Entsprechend sollen mit der gleichen Funktion table({}) Tabellen-Spalten auch ausblendbar (hide) sein. Der mod-Argument gebe die gewünschten Aktionen an. Hier einige Aufrufe:

Show Tabellenelemente: 
<a href="javascript:table({id:'myTable',mod:'table-cell',arr:[0,1,2]})"> all  </a>
<a href="javascript:table({id:'myTable',mod:'table-cell',arr:[0]})"> Produkte </a>
<a href="javascript:table({id:'myTable',mod:'table-cell',arr:[1]})"> Betriebe </a>
<a href="javascript:table({id:'myTable',mod:'table-cell',arr:[2]})"> Unsätze  </a>

Hide Tabellenelemente: 
<a href="javascript:table({id:'myTable',mod:'none',arr:[0,1,2]})"> all  </a>
<a href="javascript:table({id:'myTable',mod:'none',arr:[0]})"> Produkte </a>
<a href="javascript:table({id:'myTable',mod:'none',arr:[1]})"> Betriebe </a>
<a href="javascript:table({id:'myTable',mod:'none',arr:[2]})"> Unsätze  </a>

Bitte ergänzen sie die folgende Funktion table(o) {...}.

function table(o) { var i, j, k, j_first = 0, td,

 table = document.getElementById(o.id), 
  
 tr = table.________________________________________('tr');

 for (k = 0; k < o.arr.length; k += 1) { // gewünschte Kombinationen
 
  for (j = ___________; j < tr.length; j += 1) { 
  
    td = _____________.getElementsByTagName('td');

    for (i = 0; i < td.length; i += 1) { // cell's

      switch (o.mod) { 
      
      // hide:
      case 'none': if (i === ____________) { td[i].style.__________ = o.mod; }
      break;

      // show:
      case 'table-cell': if (o.arr[k] === ______) { td[i].style.display = _________; }
      break;

      // rechtsbündig
      case 'right': if (i === o.arr[k]) { td[i].style.____________ = _____________; }
      break;

      // je zeile
      default: if (___________ === o.arr[k]) { td[i]._____________ = o.mod; }
      break;
      } // ende switch
    } // ende for i
  } // ende for j
 } // ende for k 
}

Bitte ergänzen:

window._____________ = function () {

  table( { id: 'myTable', mod:'none',       arr:[__________]});

  table( { id: 'myTable', mod:'__________', arr:[__________]});

  table( { id: 'myTable', mod:'__________', arr:[__________]});
}
Produkte Betriebe Unsätze
Art-Deko-Steine XQuarz GmbH 2 712 456.00
Frischkäse Hans Schnell, Hintertupfingen 12 456.50
Bio-Eier Freiland-AG, Freilichtbergen 9 456.99
Ü: getElementsByAttribute leider keine DOM-Funktion ...

Die folgende Funktion dom erzeugt ein Objekt, mit den Funktionen root und getElementsByAttribute. Infolge der Rekursivität können ab dem root-Knoten alle nodes durchlaufen und alle jene nodes aufgesammelt werden, die das gewünschte Attribut haben.

Code Snippet: getElementsByAttribute() nach Crockford
  1. var dom = (function() {
  2.   var root_node = document.body,
  3.   
  4.   get_childs = function walk(node, fn) {
  5.    fn(node);
  6.    node = node.firstChild;
  7.    while(node) {
  8.      walk(node, fn);
  9.      node = node.nextSibling;
  10.    }
  11.   };
  12.   return {
  13.   getElementsByAttribute: function(att, val){ var r = [];
  14.     get_childs(root_node, function(node) {
  15.      var akt = node.nodeType === 1 && node.getAttribute(att);
  16.      if(typeof akt === 'string' && (akt === val || typeof val !== 'string')) {
  17.         r.push(node);
  18.      }
  19.    }); return r;
  20. },
  21. root: function(node) { root_node = node || document.body; return this;}
  22. };}());
Ü: Sortieren eines Array von Objekten

Ein Array arr, dessen Elemente aus Objekten besteht, soll nach den Objekt-keys's (hier a, b, c) sortiert werden.

var arr = [ // Beispiel:
 {a:'a1',b:'b5',c:3},{a:'a2',b:'b5',c:2},{a:'a1',b:'b4',c:3},
 {a:'a2',b:'b4',c:1},{a:'a4',b:'b5',c:2},{a:'a9',b:'b4',c:3},
 {a:'a3',b:'b6',c:3},{a:'a3',b:'b5',c:2},{a:'a6',b:'b7',c:3},
];
Code Snippet: Sortiere Array von Objekten nach name
  1. var by = function(name, minor) { // nach crockford
  2.   return function(o,p) { var a,b;
  3.     if(o && p && typeof o === 'object' && typeof p === 'object') {
  4.       a = o[name];
  5.       b = p[name];
  6.       if ( a === b ) { return typeof minor === 'function' ? minor(o,p) : 0; }
  7.       if(typeof a === typeof b) { return a < b ? -1 : 1; }
  8.       return typeof a < typeof b ? -1 : 1;
  9.     } else {
  10.       throw { name: 'Error',
  11.         message: 'Expected an object when sorting by ' + name
  12.       };
  13.     }
  14.   };
  15. };
Ü: Einmischen von Objekten (fortgeschritten) var obj = Object.merge(o1, o2, ...);

Mit Hilfe von Object.method('extend', function (o) { ... } ist eine Methode .extend(o1[,o2[,o2[,o3,...]]]) zu schreiben, die ein oder mehrer Objekte zusammenmischt und das resultierende Objekt zurück gibt. Beispiel:

 var o1 = { a : 11, 'b' : 12, c: 13 };
 var o2 = { a : 21,           c: 23, d: 24 };
  
 var obj = Object.merge(o1, o2);

Dies ergibt obj = {a: 21, b: 12, c: 23, d: 24 };

Bitte ergänzen:

 if (!Function.prototype.method) {
      Function.prototype.method = function (name, func) {
      if (!this.prototype[name]) { this.prototype[name] = func; }
      };
 }

Object.method('merge', _________________ (o) { 

  var k, v, undef, i = 0, r = {}, 

  len = ____________________.length;

  while (i < len) { o = arguments[i];

    for (k in o) {

      if (___.hasOwnProperty(____)) {  v = _________; 

        if (v !== undef) { _________ = v; }
      }
    } i += 1;
  } return r;
});
Ü: Array und Callback-Funktion (einfach) einfache loop-Funktion

Zum Durchlaufen eines Array arr=[...] ist eine Funktion loop(arr, fn) zu schreiben. Neben dem Array arr ist als Argument eine Callbackfunktion fn(el,i) zu übergeben, der ein Bezeichner für das aktuelle Arrayelement el=arr[i] und der aktuelle Index i ist.

Beispiel für einen Aufruf:

var num = 0, arr_der_elemente = [], arr_der_indizes = []; 
loop([10, 11, 12], function(el, i) { 
     arr_der_elemente.push(el);
     arr_der_indizes.push(i); 
});

Bitte ergänzen sie die folgende Funktion:

function loop(arr, fn) { var i;
  for ( i = 0; i < arr.length; i += 1 ) { 

    fn.____________( arr, __________, ____________ );
  } 
} 

Was ergibt sich für den Aufruf

var arr_der_elemente = [], 
    arr_der_indizes  = []; 

  loop( [10, 11, 12], function(el, i) { 
       arr_der_elemente.push(el);
       arr_der_indizes.push(i); 
  });

  // nun ist 
  // arr_der_indizes   = __________________________

  // arr_der_elemente  = __________________________
Ü: Array und Callback-Funktion (fortgeschritten) mit Array.method('loop', ...){...} und .call-Aufruf

Zum Verbergen des ('recht unleserlichen') prototype-Formalismus soll die Hilfsfunktion Function.prototype.method (Crockford) verwendet werden. Beispiel für einen Aufruf der zu schreibenden Funktion loop(fn) mit einer User-Callback-Funktion fn:

var r1 = [10, 11, 12].loop(function (el, i) {
    if (i === 1) {delete el; } else {return el*el; }
});

In einer Callback-Funktion wird die Funktion (mit den aktuellen Argument)

aufgerufen durch _______________________________________________________

Ergänzen sie bitte:

  if (!Function.prototype.method) {
    Function.prototype.method = function (name, func) {
      if (!this.prototype[name]) {
        this.prototype[name] = func;
      }
    };
  }

Array.method('loop', function (fn) { var i, arr = ______________, r = [];

  for ( i = 0; i < arr.length; i += 1 ) { 

    r.________________( fn.______________( arr, _____________, __________ ));

  } return r;
});


// Aufruf-Beispiele:
var sum = 0, 
    r1 = [10, 11, 12].loop( function (el, i) { 
              if (i === 1) { delete el; } else { return el*el; } 
         }),
    r2 = [10, 11, 12].loop(function (el) { 
              sum += el; 
         }),
    r3 = Array.prototype.loop.call("ABC", function(c) { 
               return c.charCodeAt(0); 
         });

  // nun ist 

  // r1   = __________________________
  
  // sum  = __________________________
  
  // r2   = __________________________