JavaScript destructuring

Neulich bei uns im Slack: Wieso funktioniert das nicht mit dem destructuring?

Tomate auf den Augen?

Siehst Du das Problem? - Wir haben ein bisschen gebraucht, ehrlich gesagt:

class Destructure {
    constructor({age, name, nr} = {}) {
        var age = age;
        var name = name;
        var nr = nr;
    }
    print() {
        console.log(this.age + this.name + this.nr);
    }
};
let instance = new Destructure(18, 'Ralph', 016255446262);
instance.print();
console.warn('Not working! at ' + new Date(2020, 3, 1, 4, 20).toString());

Alle haben gerufen: Du musst natürlich ein Object im Konstruktor übergeben! Sowas wie:

new Destructure({age: 18, name: 'Ralph', nr: 016255446262});

Aber warum funktioniert das dann immer noch nicht? Oh Mann. Bis mal jemand das var entdeckt hat. Es muss natürlich heissen:

constructor({age, name, nr} = {}) {
        this.age = age;
        this.name = name;
        this.nr = nr;
    }

Und überhaupt! var ist evil

Na, was kommt hierbei raus?

var foo = "foo";
function bar() {
  console.log(foo);
  foo = "bar";
  var foo = "baz";
}
console.log(foo);
bar();
console.log(foo);

Auflösung: foo, undefined, foo

Es ist so, dass bei var das sogenannte Hoisting zum Einsatz kommt. var-Variablen werden immer innerhalb ihres Scopes zu allererst nur initialisiert, allerdings nicht zugewiesen. Das var foo="baz" innerhalb der Funktion sorgt also durch hoising übersetzt dafür:

var foo = "foo";
function bar() {
  var foo;
  console.log(foo);
  foo = "bar";
  foo = "baz";
}
console.log(foo);
bar();
console.log(foo);

Bei let wäre es rein technisch sogar das gleiche Spiel, wir haben aber das Glück, dass dank es2015 im Block Scope ein “menschengemachter” Fehler direkt ausgeschlossen wird. Also etwas wie:

var foo = "foo";
function bar() {
  console.log(foo);
  let foo = "bar"
}
bar();

Führt zu einem Fehler, obwohl man hier keinen erwarten würde. Es ist also nicht zwingend ein Unterschied zwischen let und var (auch wenn es natürlich sehr nah daran ist) sondern ein Unterschied ob Hoisting durch die Umgebung erlaubt ist oder nicht. Bei var ist es das eben nach wie vor.

Also. Bitte bitte, verwendet niemals var !

Merkregel: let deklariert für einen Block (block scoped), also innerhalb von { }, während var am Anfang der Funktion deklariert (function scoped). let funktioniert also wie in jeder anderen Programmiersprache auch, var ist das wie es PHP macht (bzw. würde, wenn Lerdorf nicht so faul gewesen wäre…).