Tag Archives: JavaScript

Quick-Hints #7

Als Webentwickler muss man sein Produkt ständig in mehreren Browsern und am besten noch in mehreren Umgebungen testen. Hier eine schöne Möglichkeit: http://blog.mattbailey.co/post/50337824984/grunt-synchronised-testing-between-browsers-devices

Mit SVG-Grafiken in Webseiten kann man viele schöne Dinge anstellen. Zum Beispiel ein Logo / eine Schrift animieren: http://jakearchibald.com/2013/animated-line-drawing-svg/

Ein paar nette CSS3 Effekte für Menüs / Links sind unter folgendem Link zu finden: http://tympanus.net/Development/CreativeLinkEffects/. Um diese auch in vielen Browsern nutzen zu können, empfiehlt sich der Einsatz eines Autoprefixers, zum Beispiel: http://css-tricks.com/autoprefixer/

Für Fälle, in denen man das letzte Element eines Arrays möchte, gibt es viele Möglichkeiten. Wenn man wert auf die Performance legt sollte man ganz klar “array[array.length – 1]; benutzen. Siehe: http://jsperf.com/get-last-item-from-array/10

Quick-Hints #6

Mit CSS3 lassen sich nette Hover-Effekte auf Icon-Buttons zaubern

Google hat einen Proxy zum Debuggen von iOS WebView-Anwendungen veröffentlicht (Github). Hiermit können Hybrid-Apps auf dem richtigen Gerät laufen gelassen und per Proxy in den Chrome-DevTools auf dem Mac oder PC gedebugt werden.

Adobe hat für den Brackets Code Editor ein nettes Feature vorgestellt: Photoshop-Dateien können direkt in den Editor geladen und im Coding verwendet werden. Das bedeutet, dass man zum Beispiel das Header-Logo anklickt, den passenden CSS-Code bekommt und das Logo als png/jpg fertig ausgeschnitten abgelegt wird. Noch besser wird es bei Linear-Gradients die aus Photoshop direkt in CSS Angaben gewandelt werden.

http://thenounproject.com/ ist auf Kickstarter gestartet und bietet nun schon allerhand Icons unter der CC-Lizenz. Gegen eine Geringe Gebühr kann man sich auch von der Nennungspflicht des Autors freikaufen.

Ob Anfänger, Fortgeschrittener oder Profi; hier ist für jeden das passende JavaScript-eBook (kostenlos) zu finden: http://jsbooks.revolunet.com/

Mike Stay erklärt auf seinem Youtube-Kanal die Kategorientheorie anhand von JavaScript.

In diesem Blogpost findet man ein paar interessante DOM-APIs, die einen das Leben erleichtern, wenn man einen Fileupload erstellen möchte.

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.

 

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:

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 (JavaScript-)Objekt
  2. Setze den Typ des neuen Objektes auf “Object
  3. Setze die Eigenschaften (Properties) des Prototyp-Objekts als die Eigenschaften des Prototypes 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:

function new( func ) {
  var NewObject = {};
  NewObject.__proto__ = func.prototype;
  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();

Das Beispiel ist sehr flach gehalten und soll wirklich nur der groben Veranschaulichung dienen. Genau nachlesen könnt ihr die Ausführung von “new” hier:

“New” ist also eher eine Art Kopiervorgang gepaart mit der Ausführung einer (Initial-)Funktion. 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:

var noClosure = function () {
    var a = a || 1;
    var b = 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.* So können wir also auch nie wieder auf einen Wert, der in der Funktion lebte zurückgreifen. Die Variablen “a” und “b” müssen immer neu belegt werden, da der return aus “a + b” sonst schief gehen würde. Im Context existieren a und b somit nicht. Würde der Inhalt der Funktion noch existieren, würde durch “a || 1″ a zu a zugewiesen und nicht 1.**

Schauen wir uns dagegen folgendes an:

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.

** Der || Operator gibt den linken Wert zurück, wenn dieser truthy ist, also zum Beispiel NICHT false, undefined, null. Aufgrund des Hoistings existiert a nie in dieser Methode. Wäre die Methode aber konserviert, würde nicht jedes mal der Kontext zurück gesetzt werden, ein Hoisting müsste ebenfalls nicht stattfinden und a würde somit existieren.

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

<script type="text/javascript" src="http://meinserver.de/meinScript.js"></script>
view raw gistfile1.html hosted with ❤ by GitHub

wird also quasi ein:

<script type="text/javascript">
;(function() {
console.log("Hello World")
})();
</script>
view raw gistfile1.html hosted with ❤ by GitHub

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.

JSON: {"Name": "Benny Bennet", "Website": "http://ben.nyben.net"}
JSONP: verarbeiteDaten({"Name": "Benny Bennet", "Website": "http://ben.nyben.net"})
view raw gistfile1.js hosted with ❤ by GitHub

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

<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>
view raw gistfile1.html hosted with ❤ by GitHub

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

function verarbeiteDaten( data ) {
console.log(data["Name"]);
console.log(data["Website"]);
}
view raw gistfile1.js hosted with ❤ 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:

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 hosted with ❤ 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.

/* 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 hosted with ❤ by GitHub

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