ES6-Tipps und Tricks, um Ihren Code sauberer, kürzer und leichter lesbar zu machen!

ES6-Tipps und Tricks, um Ihren Code sauberer, kürzer und leichter lesbar zu machen!

Vorlagenliterale

Vorlagenliterale erleichtern die Arbeit mit Zeichenfolgen erheblich. Sie werden mit einem Back Tick gestartet und können mithilfe von Variablen eingefügt werden ${variable}. Vergleichen Sie diese beiden Codezeilen:

var fName = 'Peter', sName = 'Smith', age = 43, job= 'photographer';var a = 'Hi, I\'m ' + fName + ' ' + sName + ', I\'m ' + age + ' and work as a ' + job + '.';var b = `Hi, I'm ${ fName } ${ sName }, I'm ${ age } and work as a ${ job }.`;

Dies macht das Leben viel einfacher und Code leichter lesbar. Sie können alles in geschweifte Klammern setzen: Variablen, Gleichungen oder Funktionsaufrufe. Ich werde diese in Beispielen in diesem Artikel verwenden.

Syntax Block Scoping

JavaScript wurde immer von Funktionen erfasst, weshalb es üblich wurde, die gesamte JavaScript-Datei in einen leeren, sofort aufgerufenen Funktionsausdruck (IIFE) zu verpacken. Dies wird durchgeführt, um alle Variablen in der Datei zu isolieren, sodass keine Variablenkonflikte auftreten.

Jetzt haben wir Block Scoping und zwei neue Variablendeklarationen, die an einen Block gebunden sind.

'Let' Erklärung

Dies ist ähnlich, varweist jedoch einige bemerkenswerte Unterschiede auf. Da es sich um einen Blockbereich handelt, kann eine neue Variable mit demselben Namen deklariert werden, ohne die äußeren Variablen zu beeinflussen.

var a = 'car' ;{ let a = 5; console.log(a) // 5}console.log(a) // car

Da es an einen Blockbereich gebunden ist, löst es diese klassische Interviewfrage:

"Was ist die Ausgabe und wie würden Sie sie wie erwartet zum Laufen bringen?"

for (var i = 1; i  { console.log(i); }, 1000);}

In diesem Fall wird "5 5 5 5 5" ausgegeben, da sich die Variable i bei jeder Iteration ändert.

Wenn Sie das varfür letausschalten, ändert sich alles. Jetzt erstellt jede Schleife einen neuen Blockbereich mit dem Wert für i, der an diese Schleife gebunden ist. Es ist, obwohl Sie geschrieben haben:

{let i = 1; setTimeout(() => { console.log(i) }, 1000)} {let i = 2; setTimeout(() => { console.log(i) }, 1000)} {let i = 3; setTimeout(() => { console.log(i) }, 1000)} {let i = 4; setTimeout(() => { console.log(i) }, 1000)} {let i = 5; setTimeout(() => { console.log(i) }, 1000)} 

Ein weiterer Unterschied zwischen varund letist, dass letnicht so gehisst wird, wie es varist.

{ console.log(a); // undefined console.log(b); // ReferenceError var a = 'car'; let b = 5;}

Aufgrund des engeren Geltungsbereichs und des vorhersehbareren Verhaltens haben einige Leute gesagt, dass Sie letstattdessen verwenden sollten var, es sei denn, Sie benötigen speziell das Anheben oder Lockern des Geltungsbereichs der varErklärung.

Const

Wenn Sie zuvor eine konstante Variable in JavaScript deklarieren wollten, war es üblich, die Variable in Blockkappen zu benennen. Dies würde die Variable jedoch nicht sichern - es würde nur andere Entwickler wissen lassen, dass es sich um eine Konstante handelt und nicht geändert werden sollte.

Jetzt haben wir die constErklärung.

{ const c = "tree"; console.log(c); // tree c = 46; // TypeError! }

constmacht die Variable nicht unveränderlich, sondern sperrt nur ihre Zuordnung. Wenn Sie eine komplexe Zuordnung (Objekt oder Array) haben, kann der Wert dennoch geändert werden.

{ const d = [1, 2, 3, 4]; const dave = { name: 'David Jones', age: 32}; d.push(5); dave.job = "salesman"; console.log(d); // [1, 2, 3, 4, 5] console.log(dave); // { age: 32, job: "salesman", name: 'David Jones'}}

Problem mit Block Scoping-Funktionen

Funktionsdeklarationen werden jetzt so angegeben, dass sie an das Block-Scoping gebunden sind.

{ bar(); // works function bar() { /* do something */ }}bar(); // doesn't work

Das Problem tritt auf, wenn Sie eine Funktion in einer ifAnweisung deklarieren .

Bedenken Sie:

if ( something) { function baz() { console.log('I passed') }} else { function baz() { console.log('I didn\'t pass') } } baz();

Vor ES6 wären beide Funktionsdeklarationen angehoben worden, und das Ergebnis wäre 'I didn\'t pass'egal gewesen, was somethingwar.

Jetzt bekommen wir 'ReferenceError', wie bazimmer durch den Blockumfang gebunden.

Ausbreitung

ES6 führt den ...Operator ein, der als "Spread-Operator" bezeichnet wird. Es hat zwei Hauptanwendungen: Verteilen eines Arrays oder Objekts in ein neues Array oder Objekt und Verbinden mehrerer Parameter zu einem Array.

Der erste Anwendungsfall ist der, dem Sie wahrscheinlich am meisten begegnen werden, also werden wir uns das zuerst ansehen.

let a = [3, 4, 5];let b = [1, 2, ...a, 6];console.log(b); // [1, 2, 3, 4, 5, 6]

Dies kann sehr nützlich sein, um eine Reihe von Variablen aus einem Array an eine Funktion zu übergeben.

function foo(a, b, c) { console.log(`a=${a}, b=${b}, c=${c}`)} let data = [5, 15, 2];foo( ...data); // a=5, b=15, c=2

Ein Objekt kann auch verteilt werden, indem jedes der Schlüsselwertpaare in das neue Objekt eingegeben wird. (Die Objektverbreitung befindet sich tatsächlich in Phase 4 des Vorschlags und wird offiziell in ES2018 veröffentlicht. Sie wird nur von Chrome 60 oder höher, Firefox 55 oder höher und Node 6.4.0 oder höher unterstützt.)

let car = { type: 'vehicle ', wheels: 4};let fordGt = { make: 'Ford', ...car, model: 'GT'};console.log(fordGt); // {make: 'Ford', model: 'GT', type: 'vehicle', wheels: 4}

Ein weiteres Merkmal des Spread-Operators besteht darin, dass ein neues Array oder Objekt erstellt wird. Das folgende Beispiel erstellt ein neues Array für b, cbezieht sich jedoch nur auf dasselbe Array.

let a = [1, 2, 3];let b = [ ...a ];let c = a;b.push(4);console.log(a); // [1, 2, 3]console.log(b); // [1, 2, 3, 4] referencing different arraysc.push(5);console.log(a); // [1, 2, 3, 5] console.log(c); // [1, 2, 3, 5] referencing the same array

Der zweite Anwendungsfall ist das Sammeln von Variablen in einem Array. Dies ist sehr nützlich, wenn Sie nicht wissen, wie viele Variablen an eine Funktion übergeben werden.

function foo(...args) { console.log(args); } foo( 'car', 54, 'tree'); // [ 'car', 54, 'tree' ] 

Standardparameter

Funktionen können jetzt mit Standardparametern definiert werden. Fehlende oder undefinierte Werte werden mit dem Standardwert initialisiert. Seien Sie vorsichtig - denn Null- und Falschwerte werden auf 0 gesetzt.

function foo( a = 5, b = 10) { console.log( a + b);} foo(); // 15foo( 7, 12 ); // 19foo( undefined, 8 ); // 13foo( 8 ); // 18foo( null ); // 10 as null is coerced to 0

The default values can be more than just values — they can also be expressions or functions.

function foo( a ) { return a * 4; }function bar( x = 2, y = x + 4, z = foo(x)) { console.log([ x, y, z ]);}bar(); // [ 2, 6, 8 ]bar( 1, 2, 3 ); //[ 1, 2, 3 ] bar( 10, undefined, 3 ); // [ 10, 14, 3 ]

Destructuring

Destructuring is the process of taking apart the array or object on the left hand side of the equal sign. The array or object can come from a variable, function, or equation.

let [ a, b, c ] = [ 6, 2, 9];console.log(`a=${a}, b=${b}, c=${c}`); //a=6, b=2, c=9
function foo() { return ['car', 'dog', 6 ]; } let [ x, y, z ] = foo();console.log(`x=${x}, y=${y}, z=${z}`); // x=car, y=dog, z=6

With object destructuring, the keys of the object can be listed inside curly braces to extract that key-value pair.

function bar() { return {a: 1, b: 2, c: 3}; }let { a, c } = bar();console.log(a); // 1console.log(c); // 3console.log(b); // undefined

Sometimes, you want to extract the values but assign them to a new variable. This is done using a 'key: variable' pairing on the left of the equals sign.

function baz() { return { x: 'car', y: 'London', z: { name: 'John', age: 21} }; }let { x: vehicle, y: city, z: { name: driver } } = baz();
console.log( `I'm going to ${city} with ${driver} in their ${vehicle}.`); // I'm going to London with John in their car. 

Another thing that object destructuring allows is assigning a value to multiple variables.

let { x: first, x: second } = { x: 4 };console.log( first, second ); // 4, 4

Object Literals and Concise Parameters

When you are creating an object literal from variables, ES6 allows you to omit the key if it is the same as the variable name.

let a = 4, b = 7;let c = { a: a, b: b };let concise = { a, b };console.log(c, concise) // {a: 4, b: 7}, {a: 4, b: 7}

This can also be used in combination with destructuring to make your code much simpler and cleaner.

function foo() { return { name: 'Anna', age: 56, job: { company: 'Tesco', title: 'Manager' } };} 
// pre ES6let a = foo(), name = a.name, age = a.age, company = a.job.company;
// ES6 destructuring and concise parameters let { name, age, job: {company}} = foo();

It can also be used to destructure objects passed into functions. Method 1 and 2 are how you would have done it before ES6, and method 3 uses destructuring and concise parameters.

let person = { name: 'Anna', age: 56, job: { company: 'Tesco', title: 'Manager' }};
// method 1function old1( person) { var yearOfBirth = 2018 - person.age; console.log( `${ person.name } works at ${ person.job.company } and was born in ${ yearOfBirth }.`);}
// method 2function old1( person) { var age = person.age, yearOfBirth = 2018 - age, name = person.name, company = person.job.company; console.log( `${ name } works at ${ company } and was born in ${ yearOfBirth }.`);} 
// method 3function es6({ age, name, job: {company}}) { var yearOfBirth = 2018 - age; console.log( `${ name } works at ${ company } and was born in ${ yearOfBirth }.`);} 

Using ES6, we can extract the age, name and company without extra variable declaration.

Dynamic Property Names

ES6 adds the ability to create or add properties with dynamically assigned keys.

let city= 'sheffield_';let a = { [ city + 'population' ]: 350000};a[ city + 'county' ] = 'South Yorkshire';console.log(a); // {sheffield_population: 350000, sheffield_county: 'South Yorkshire' }

Arrow Functions

Arrow functions have two main aspects: their structure and their this binding.

They can have a much simpler structure than traditional functions because they don't need the function key word, and they automatically return whatever is after the arrow.

var foo = function( a, b ) { return a * b;} 
let bar = ( a, b ) => a * b;

If the function requires more than a simple calculation, curly braces can be used and the function returns whatever is returned from the block scope.

let baz = ( c, d ) => { let length = c.length + d.toString().length; let e = c.join(', '); return `${e} and there is a total length of ${length}`;}

One of the most useful places for arrow functions is in array functions like .map, .forEach or .sort.

let arr = [ 5, 6, 7, 8, 'a' ];let b = arr.map( item => item + 3 );console.log(b); // [ 8, 9, 10, 11, 'a3' ]

As well as having a shorter syntax, it also fixes the issues that often arose around the this binding behaviour. The fix with pre-ES6 functions was to store the this reference, often as a self variable.

var clickController = { doSomething: function (..) { var self = this; btn.addEventListener( 'click', function() { self.doSomething(..) }, false ); } };

This had to be done because the this binding is dynamic. This means that the this inside the event listener and the this inside the doSomething do not refer to the same thing.

Inside arrow functions, the this binding is lexical, not dynamic. This was the main design feature of the arrow function.

Whilst lexical this binding can be great, sometimes that's not what is wanted.

let a = { oneThing: ( a ) => { let b = a * 2; this.otherThing(b); }, otherThing: ( b ) => {....} };
a.oneThing(6);

When we use a.oneThing(6), the this.otherThing( b ) reference fails as this doesn't point to the a object, but to the surrounding scope. If you are rewriting legacy code using ES6 syntax, this is something to watch out for.

for … of Loops

ES6 adds a way to iterate over each of the values in an array. This is different from the existing for ... in loop that loops over the key/index.

let a = ['a', 'b', 'c', 'd' ];// ES6 for ( var val of a ) { console.log( val );} // "a" "b" "c" "d"// pre-ES6 for ( var idx in a ) { console.log( idx );} // 0 1 2 3

Using the new for … of loop saves adding a let val = a[idx] inside each loop.

Arrays, strings, generators and collections are all iterable in standard JavaScript. Plain objects can't normally be iterated over, unless you have defined an iterator for it.

Number Literals

ES5 code handled decimal and hexadecimal number formats well, but octal form wasn't specified. In fact, it was actively disallowed in strict mode.

ES6 has added a new format, adding an o after the initial 0 to declare the number an octal. They've also added a binary format.

Number( 29 ) // 29Number( 035 ) // 35 in old octal form. Number( 0o35 ) // 29 in new octal form Number( 0x1d ) // 29 in hexadecimal Number( 0b11101 ) // 29 in binary form

And Much More…

There is much, much more that ES6 offers us to make our code cleaner, shorter, easier to read and more robust. I aim to write a continuation of this article covering the less well known bits of ES6.

If you can’t wait that long, have a read of Kyle Simpson’s You Don’t Know JS book on ES6, or check out this brilliant little website!

Do you want to become a developer and get your first software job? Download the 7 Steps to Becoming a Developer and Getting Your First Job.

NÄCHSTER -> So sichern Sie Ihren Traumjob. Beherrsche den Interviewprozess

Wenn Ihnen das gefallen hat und Sie es hilfreich fanden, zeigen Sie Ihre Unterstützung, indem Sie wegklatschen und abonnieren, um weitere Artikel wie diesen zu erhalten!