Quick-Hints #5

  1. Für umfangreiches debuggen von JavaScript Client- und Server-Code: https://trace.gl/
  2. Mehr Performance im Siteflow dank Prefetch dank HTML5: Link
  3. Ein Blogsystem, kein CM-System; Ghost will die Alternative zu WordPress für Blogger werden und hat dafür ausreichend Kapital per Kickstarter eingesammelt.
  4. Schon heute in ES6 entwickeln und als ES5 ausliefern, Addy Osmani hat beschrieben wie es geht. Dank Grunt.js kann dies völlig automatisiert geschehen.
  5. two.js ist eine API für 2D-Grafiken im Browser unabhängig vom Context.
  6. Noch mehr Performance für WebApps gibt es dank den Tipps von Mozilla für Apps auf Firefox OS in JavaScript.

 

HTTP Digest Authentication & verschlüsselte (md5) Ablage des Passworts in der DB

Bei einer kürzlich geschriebenen WebApp benutzte ich die HTTP Digest Auth für die Authentifizierung der User. Das einzige Problem hierbei ist, dass das Passwort des Nutzers im Klartext vorhanden sein muss. Ich wollte das Passwort aber nicht als Klartext in der Datenbank haben (obvious). Die kleine aber feine Lösung:

Den ersten Part der Digest-Checksum (A1), siehe Wikipedia, in der Datenbank ablegen. Dieser ist der md5-Hash des kombinierten Strings aus UserID, Realm (beliebiger Name) und Passwort: A1 = md5(uid:realm:pass)

Quick-Hints #4

Ein paar kurze Anmerkungen und Hinweise zu verschiedenen Themen, die nicht unbedingt einen ganzen eigenen Post benötigen aber trotzdem erwähnenswert sind:

  • In Firefox gibt es ein nettes “Phänomen” bezüglich des Function-Hoistings: Theoretisch würde man eine Funktionsdeklaration unabhängig von der Platzierung im Sourcecode benutzen können, da diese immer an erste Stelle im Code gehoben wird. Immer? Erst glaubte ich es sei ein Bug, aber Firefox entspricht hier nur der Spec. Innerhalb von Blocks (z.B. if(){}) “funktionierte” das Hoisting nicht wie erwartet. Ich konnte die Funktion nicht nach dem Aufruf deklarieren. Warum? Der eigentliche Grund ist, dass innerhalb von Blocks nur Statements erlaubt sind und eine Funktionsdeklaration ist kein Statement sondern ein SourceElement. Die meisten JavaScript-Engines behandeln eine Functionsdeklaration aber wie ein Statement, was natürlich nicht korrekt ist.

  • Automatische hyphenation (weicher Wortumbruch beim erreichen des Randes) ist in CSS3 möglich und in vielen Browsern auch unterstützt. Um eine höhere Abdeckung zu erreichen kann ein JavaScript herangezogen werden: Hyphenator.js

  • Die Geeksphones mit Firefox OS sind seit heute zum Kauf erhältlich. Für ~90€ oder ~150€ gibt es gut ausgestattete Smartphones eines spanischen Herstellers. Das sind natürlich absolute Kampfpreise und es wäre allein aufgrund des Betriebssystems sicherlich eine Bestellung wert. Apps für Firefox OS können in HTML5/CSS3/JavaScript entwickelt werden.

 

Semikolon Wars

Semikolon

Dank der Automatic Semicolon Insertion (ASI) muss man in JavaScript nicht jede Angabe mit einem Semikolon beenden. In fast allen Fällen wird bei einem Zeilenumbruch automatisch durch den JavaScript-Interpreter ein Semikolon eingefügt.

Aus dieser Tatsache ergbit sich ein Streit darum, ob man JavaScript nun mit oder ohne Nutzung der ASI programmieren soll. Sprich: Dürfen wir faul sein; trägt es der Lesbarkeit zu, wenn wir JavaScript-Statements ohne Semikolon, nur mit einem Zeilenumbruch, beenden. Ob es mit einer Diskussion auf Github gestartet ist oder es nur der erste richtige öffentliche Streit war, weiss ich nicht, aber der Entwickler “fat” verhilt sich nicht sonderlich klug (aus meiner Sicht). Er ist einer der Entwickler von Bootstrap und bei Twitter angestellt. Anstelle auf Wünsche der Community einzugehen oder diese zumindest vernünftig Begründet abzulehnen, legt er sich mit einem bekannten JS-Guru (Douglas Crockford) und einem großen Teil der restlichen Nutzer in einer ungeschickten Art und Weise an.

Es gibt Gründe für und Gründe gegen das Nutzen von Semikolons in JavaScript. Der Erfinder der Programmiersprache, Brendan Eich, hatte sich dazu auch in seinem Blog geäußert. Meiner Meinung nach gibt es aber ein Argument, was alle anderen aussticht: Das Weglassen von Semikolons kann in wenigen Fällen Bugs verursachen, das Benutzen hingegen nicht.

PS: Mittlerweile scheinen übrigens einige Kommentare von “fat” gelöscht worden zu sein, was der Reputation seines Arbeitsgebers und seiner selbst sicher entgegen kommt.

Quick-Hints #3

Mal wieder eine kleine Ansammlung von Tipps und interessanten Infos.

Was macht das “new” Keyword in JavaScript?

new Keyword JavaScriptIn meinem Post zum Versuch soetwas wie Klassen in JavaScript zu ermöglichen, hatte ich geschrieben, dass “new” in JavaScript irreführend ist. Nehmen wir folgendes Beispiel:

1 2 3 4 5 6 7 8
function Example( a ) { this.a = 2 }
Example.prototype = {
a: 1,
b: function() { console.log(this.a); }
};
 
var test = new Example();
test.b();

“New” kann man eigentlich als Funktion betrachten und was in dieser, quasi hinter den Kulissen, passiert ist folgendes:

  1. Erstelle ein neues Objekt
  2. Setze den Prototyp (den Verweis zum Prototyp) des erstellten Objekts auf Example (welches eine Funktion ist, was in JavaScript auch ein Objekt ist).
  3. Setze die Eigenschaften (Properties) des Prototyp-Objekts als die Eigenschaften des neu erstellten Objekts.
  4. Führe die Funktion Example aus. Übergebe dieser Funktion hierfür das neu erstellte Objekt als “this” und sofern vorhanden übergebe die restlichen Parameter.
  5. Gebe das erstellte Objekt zurück.

Als Code sieht das dann in etwa so aus:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
function new( func ) {
var NewObject = {};
NewObject.__proto__ = func;
NewObject.prototype = func.prototype;
for( property in func.prototype ) {
NewObject[property] = property;
}
func.apply(NewObject, func.arguments);
return NewObject;
}
 
function Example( a ) { this.a = 2 }
Example.prototype = {
a: 1,
b: function() { console.log(this.a); }
};
 
var test = new(Example());
test.b();

“New” ist also eher eine Art Kopiervorgang gepaart mit der Ausführung einer Funktion des geklonten Objekts. Es ist somit nicht zu verwechseln mit dem “new” in Java oder ähnlichen Sprachen. Was ich in dem Zusammenhang mit irreführend meine ist, dass das “new” in JavaScript eigentlich eingeführt wurde, damit sich Java- und andere Entwickler wohler fühlen, es aber eigentlich etwas ganz anderes macht, als es ein Java-Entwickler erwartet.

Wenn ich in diesem Artikel von Prototyp sprach, meinte ich immer den Function-Prototype in JavaScript. Natürlich ist es nicht möglich eine Funktion “new” zu bennen, das Wort ist reserviert und dient im Beispiel nur der Veranschaulichung.

JavaScript Closures leicht und klar erklärt

Mit der Kategorie “LUKE” – “leicht und klar erklärt” möchte ich eine neue Serie starten, in der ich einige Dinge beschreibe / erkläre. Im Gegensatz zu den meisten online Ressourcen werde ich es aber immer möglichst leicht halten und möchte klar und eingehend erklären, was Sache ist. Man könnte sagen, ich versuche es mit dem Wortschatz eines Anfängers und nicht mit dem eines Profis zu erklären. Wörter, die eventuell trotzdem unklar sein könnten, versuche ich möglichst immer mit einem Link zu hinterlegen, der diesen Begriff dann näher erklärt. Häufig findet man hinter Begriffen in Klammern “()” auch den Fachbegriff.

Als Eröffnungsthema der Kategorie nehme ich die Closures. Ein Closure (engl. Abschluss) ist in JavaScript ein Rückgabewert einer Funktion. Dieser Rückgabewert wiederum ist auch eine Funktion. Ein Closure ist also eine Funktion, die von einer Funktion zurückgegeben wird. Das besondere an dieser Funktion ist, dass sie quasi die Zeit einfrieren kann. Sie merkt sich ihre Umgebung (Context) zum Erstellungszeitpunkt und kann auf diese später wieder zugreifen, obwohl die Umgebung eigentlich nicht mehr existiert.  Wenn eine Funktion ihr Ende erreicht hat wird alles von ihr bekannte durch den Müllsammler (Garbage Collector) weggeräumt. Seht euch folgendes Beispiel an:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var noClosure = function () {
var a = 1;
var b = 2;
 
b = b + 1;
return a + b;
}
console.log(noClosure());
console.log(noClosure());
console.log(noClosure());
console.log(noClosure());
 
=> 4
=> 4
=> 4
=> 4

Wenn die Funktion “noClosure” aufgerufen wurde, gibt sie am Ende das Ergebnis von “a + b” zurück. Nachdem sie das getan hat, existieren die Variablen im Programm nicht mehr, weil Sie für den Müllsammler freigegeben wurden.* Das sehen wir sehr schön daran, da der Rückgabewert immer 4 ist, der Inhalt also mit jedem Aufruf immer neu erstellt wird.

Schauen wir uns dagegen folgendes an:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
var closure = (function() {
var a = 1;
var b = 2;
 
return function () {
b = b + 1;
return a + b;
}
})();
console.log(closure());
console.log(closure());
console.log(closure());
console.log(closure());
 
=> 4
=> 5
=> 6
=> 7

Hier wird der Inhalt nicht jedes mal neu erstellt. Die Variable “b” hat nach jedem Aufruf einen um 1 erhöhten Wert zugewiesen. Wir konservieren also die Werte der Variable “a” und “b” anstelle sie jedes mal neu zu erstellen.

Closures sind ne tolle Sache, damit kann man vieles wirklich wirklich gutes und nützliches machen. Zum Beispiel Caching, Module-Patterns, private Werte usw. Ich bin mir abschließend aber noch nicht ganz sicher, ob man in JS wirklich soetwas wie “private” benötigt.

* Der Garbage Collector sammelt alle Dinge auf (und gibt den davon belegten Speicher wieder frei), die nicht mehr zu erreichen sind. Nicht mehr zu erreichen sind sie, wenn sie außerhalb der Sichtweite / des Anwendungsbereichs (Scope) sind.

JSONP – Eine Methode um die Same-Origin-Policy zu umgehen

Die Same-Origin-Policy untersagt clientseitigen Skriptsprachen wie JavaScript Anfragen an Server zu stellen, die nicht der gleichen Herkunft / dem gleichen Speicherort entsprechen. Das ist eigentlich eine gute Sache, da es der Sicherheit beiträgt und gut zur Natur von JavaScript passt. Es gibt aber Fälle, bei denen man beabsichtigt Anfragen an andere Server stellen will. Als offensichtliches Beispiel wäre hier die Datenabfrage bei Diensten wie Twitter oder ähnlichen. Hierfür gibt es zum Beispiel JSONP, JSON with Padding.

Was steckt hinter JSONP

JSONP nutzt eine “Lücke” um eine HTTP-Anfrage an einen Server zu senden, der nicht der gleichen Herkunft (Origin) wie der des JavaScripts entspricht. Die SRC-Attribute im Script-Tag können GET-Anfragen an Server beliebiger Herkunft senden. GET eigentlich im Sinne von: Schick mir mal das JavaScript (meist in Form einer .js-Datei) und nicht im Sinne von; Schick mir mal die JSON Daten.

Was aber beim Script-Tag eigentlich passiert ist, dass der Browser die JavaScript-Datei lädt und ausführt. Aus

1
<script type="text/javascript" src="http://meinserver.de/meinScript.js"></script>

wird also quasi ein:

1 2 3 4 5
<script type="text/javascript">
;(function() {
console.log("Hello World")
})();
</script>

Wie funktioniert nun JSONP?

JSONP nutzt eben beschriebenes Prinzip, indem der Server auf diese GET-Anfrage nicht mit normalen JSON-Daten antwortet, sondern noch ein Extra hinzufügt. Die JSON-Daten werden in einem Funktionsaufruf gehüllt, dieser Funktionsaufruf ist das P für Padding in JSONP. Das ist nicht unbedingt die beste Namenswahl gewesen, da Padding bei Webentwicklern durch CSS mental schon vorbelegt ist. Hier heisst es aber einfach nur, wie gesagt, dass die JSON-Daten in einem Funktionsaufruf gehüllt werden.

1 2
JSON: {"Name": "Benny Bennet", "Website": "http://ben.nyben.net"}
JSONP: verarbeiteDaten({"Name": "Benny Bennet", "Website": "http://ben.nyben.net"})
view raw gistfile1.js This Gist brought to you by GitHub.

In der Regel teilt man dem Server per Parameter mit, in welchen Funktionsaufruf er die Daten hüllen soll.

1 2 3 4 5
<script type="text/javascript" src="http://some.tld/web/service?callback=verarbeiteDaten"></script>
... wird zu
<script type="text/javascript">
verarbeiteDaten({"Name": "Benny Bennet", "Website": "http://ben.nyben.net"})
</script>

Der geneigte JavaScripter müsste jetzt also nur noch irgendwo die Funktion “verarbeiteDaten” implementieren…

1 2 3 4
function verarbeiteDaten( data ) {
console.log(data["Name"]);
console.log(data["Website"]);
}
view raw gistfile1.js This Gist brought to you by GitHub.

…und würde in seiner Console in diesem Beispiel die Ausgaben “Benny Bennet” und “http://ben.nyben.net” erhalten. Als Nachteil ist hier natürlich zu erwähnen, dass man dem Service 100% vertrauen können muss.

JavaScript Class à la bennybennet

Eines der schwierigsten Dinge, zumindest für mich, beim lernen von JavaScript, ist die Gewöhnung an funktionale Programmierung und die Implementierung von OO. Letzteres, weil JavaScript nicht die gängige Syntax aus andere C-Like-Block-Syntax-Sprachen benutzt, um “Objektbaupläne” aka Klassen zu beschreiben. In JavaScript gibt es keine Klassen. Um Objekte in JavaScript zu definieren, müssen wir also auf ein anderes Mittel zurückgreifen.

Eine Beispiel-Klasse in Java:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
package de.bennybennet.examples;
 
public class Example extends Parent {
String exampleVarPP = "I'm only visible for every class in this package.";
private String exampleVarPriv = "I'm only visible for this class";
public Example() {
System.out.println("...entered the constructor");
}
public String getExampleVarPriv() {
System.out.println("...entered method of Example: Getter exampleVarPriv.");
return this.exampleVarPriv;
}
}
view raw Example.java This Gist brought to you by GitHub.

JavaScript bietet für die Definition von Objekten sogenannte Prototypen. Ist man es gewohnt mit Klassen zu programmieren, dauert es häufig eine Weile, bis man prototypenbasierte Programmierung versteht. Der Sinn hinter Objekten und deren Vererbbarkeit ist die Wiederverwendung von Code. In Klassenbasierten sprachen geschieht dies, logisch, durch Klassen. Klassen können von anderen Klassen erben. Objekte entstehen durch Instanzierung von Klassen. In prototypbasierten Sprachen, werden Objekte durch das Klonen bereits bestehender Objekte erzeugt. Hierdurch kann auch eine Vererbung realisiert werden. Das Objekt “Child” wird aus einem Klon vom Objekt “Parent” erstellt und kann anschließend um Attribute und Methoden erweitert werden, die dann nur dem Objekt “Child” und Klons vom Objekt “Child” zur Verfügung stehen, nicht aber Objekt Parent oder weiteren Klons von diesem. Das Objekt Parent war der Prototyp für den Klon “Child”. Es werden keine Instanzen im Java-Sinne von Objektbauplänen (Klassen, Prototypen) in JavaScript erzeugt, weshalb das “new” in JavaScript sehr irreführend ist. Weiteres und näheres möchte ich gerne in einem anderen Post beschreiben.

Die folgende Notation, um klassenähnliche Definition von Objekten in JavaScript zu haben, ist hauptsächlich als akademisch anzusehen. Ich habe sie in meinen ersten Begegnungen mit JavaScript abseits von jQuery erstellt, hauptsächlich um JavaScript besser zu verstehen. Ist JS dein täglich Brot (oder besser: soll es das werden), empfehle ich stark, keine klassenähnlichen Konstrukte in JavaScript zu verwenden. Setzte dich intensiv mit prototypenbasierter Programmierung auseinander und verstehe, wie diese in JavaScript umgesetzt ist / funktioniert.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
/* Simple JavaScript Inheritance
* First draft!
* @author Benny Bennet Jürgens (http://ben.nyben.net)
* CC-by-sa 3.0 - please provide my name and url
*/
;(function() {
"use strict";
this.BBClass = function(ctor, proto) {
ctor.prototype = proto || {};
ctor.prototype.constructor = ctor;
ctor.extends = function(parent) {
function ChildBB() {
parent.prototype.constructor.apply(this, arguments);
ctor.apply(this, arguments);
};
ChildBB.prototype = ( typeof Object.create !== 'function') ?
(function(parent) {
function F() {};
F.prototype = parent.prototype;
var prototype = new F();
prototype.constructor = ChildBB;
return prototype;
})(parent)
: Object.create(parent.prototype, { constructor: { value: ChildBB, enumerable: false }});
return ChildBB;
}
return ctor;
}
}).call(this);
 
var Person = BBClass(function(isDancing) {
console.log("person");
this.dancing = isDancing;
});
 
Person.prototype.dance = function() {
return this.dancing;
};
 
var Ninja = BBClass(function(isDancing) {
console.log("ninja");
}).extends(Person);
 
Ninja.prototype.swingSword = function() {
return true;
};
Ninja.prototype.arraytest = [1,2,3,4];
 
var p = new Person(true);
var n = new Ninja(false);
 
Person.prototype.test2 = function() { console.log("test2 bestanden"); };
 
console.log(n.arraytest);
console.log(p.dance());
console.log(n.dance());
console.log(n.swingSword())
p.test2();
n.test2();
console.log("inherit ok?")
console.log( p instanceof Object);
console.log( p instanceof Person);
console.log( p instanceof Person && p instanceof Object && n instanceof Ninja && n instanceof Person && n instanceof Object);
 
=> person
=> person
=> ninja
=> [1,2,3,4]
=> true
=> false
=> true
=> test2 bestanden
=> test2 bestanden
=> inherit ok?
=> true
=> true
=> true
view raw class.js This Gist brought to you by GitHub.

Ich empfehle auch die Kommentare im Gist einmal durchzulesen. Dort habe ich meine Gedanken während der Entwicklung runtergeschrieben.

Quik-Hints #2

Ein paar kurze Anmerkungen und Hinweise zu verschiedenen Themen, die nicht unbedingt einen ganzen eigenen Post benötigen aber trotzdem erwähnenswert sind: