ES6 tip og tricks til at gøre din kode renere, kortere og lettere at læse!

ES6 tip og tricks til at gøre din kode renere, kortere og lettere at læse!

Skabelonbogstaver

Skabelonbogstaver gør det meget lettere at arbejde med strenge end før. De startes med et tilbage-kryds og kan få variabler indsat ved hjælp af ${variable}. Sammenlign disse to kodelinjer:

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 }.`;

Dette gør livet langt enklere og kode lettere at læse. Du kan placere alt inden i de krøllede seler: variabler, ligninger eller funktionsopkald. Jeg bruger disse i eksempler i hele denne artikel.

Syntaks Block scoping

JavaScript er altid blevet afgrænset af funktioner, hvorfor det var blevet almindeligt at pakke hele en JavaScript-fil ind i et tomt straks påkaldt funktionsudtryk (IIFE). Dette gøres for at isolere alle variablerne i filen, så der er ingen variable konflikter.

Nu har vi blokafgrænsning og to nye variabeldeklarationer, der er bundet til en blok.

'Lad' erklæring

Dette ligner, varmen har et par bemærkelsesværdige forskelle. Fordi det er blokomfanget, kan en ny variabel med samme navn erklæres uden at påvirke ydre variabler.

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

Fordi det er bundet til et blokomfang, løser det dette klassiske interviewspørgsmål:

"hvad er output, og hvordan får du det til at fungere, som du forventer?"

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

I dette tilfælde udsender den "5 5 5 5 5", fordi variablen i ændres på hver iteration.

Hvis du slukker for varfor, letændres alt. Nu opretter hver løkke et nyt blokomfang med værdien for jeg bundet til den løkke. Det er skønt du har skrevet:

{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)} 

En anden forskel mellem varog leter, at den letikke hejses, som den varer.

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

På grund af dens strammere scoping og mere forudsigelige opførsel har nogle mennesker sagt, at du skal bruge i letstedet for var, undtagen hvor du specifikt har brug for løftning eller løsere scoping af varerklæringen.

Konst

Hvis du tidligere ville erklære en konstant variabel i JavaScript, var det konvention at navngive variablen i blokhætter. Dette ville imidlertid ikke sikre variablen - det lod bare andre udviklere vide, at den var konstant og ikke skulle ændres.

Nu har vi consterklæringen.

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

constgør ikke variablen uforanderlig, låser bare dens opgave. Hvis du har en kompleks opgave (objekt eller matrix), kan værdien stadig ændres.

{ 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 med blok-scoping-funktioner

Funktionserklæringer er nu specificeret til at være bundet til at blokere scoping.

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

Problemet kommer, når du erklærer en funktion inde i en iferklæring.

Overvej dette:

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

Før ES6 ville begge funktionserklæringer have været hejst, og resultatet ville have været 'I didn\'t pass'uanset hvad der somethingvar.

Nu får vi 'ReferenceError', som bazaltid er bundet af blokområdet.

Spredning

ES6 introducerer ...operatøren, der kaldes 'spredningsoperatør'. Det har to hovedanvendelser: spredning af et array eller objekt i et nyt array eller objekt og sammenføjning af flere parametre til et array.

Den første brugssag er den, du sandsynligvis støder mest på, så vi ser først på det.

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

Dette kan være meget nyttigt til overførsel af et sæt variabler til en funktion fra en matrix.

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

Et objekt kan også spredes ved at indsætte hvert af nøgleværdiparene i det nye objekt. (Objektspredning er faktisk i fase 4 i forslaget og vil officielt være i ES2018. Det understøttes kun af Chrome 60 eller nyere, Firefox 55 eller nyere og Node 6.4.0 eller nyere)

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

Et andet træk ved spread-operatøren er, at det opretter et nyt array eller objekt. Eksemplet nedenfor opretter et nyt array til b, men crefererer bare til det samme 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

Den anden brugssag er at samle variabler sammen i en matrix. Dette er meget nyttigt, når du ikke ved, hvor mange variabler der sendes til en funktion.

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

Standardparametre

Funktioner kan nu defineres med standardparametre. Manglende eller udefinerede værdier initialiseres med standardværdien. Bare vær forsigtig - fordi null og falske værdier tvinges til 0.

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

Standardværdierne kan være mere end bare værdier - de kan også være udtryk eller funktioner.

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 ]

Destrukturer

Destrukturering er processen med at adskille arrayet eller objektet på venstre side af ligestillingen. Matrixen eller objektet kan komme fra en variabel, funktion eller ligning.

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

Ved objektdestruktion kan nøglerne til objektet anføres i krøllede seler for at udtrække dette nøgleværdipar.

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 har tilføjet et nyt format og tilføjer et oefter initialen for 0at erklære nummeret som et oktalt. De har også tilføjet et binært 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

Og meget mere…

Der er meget, meget mere, som ES6 tilbyder os til at gøre vores kode renere, kortere, lettere at læse og mere robust. Jeg sigter mod at skrive en fortsættelse af denne artikel, der dækker de mindre kendte bits i ES6.

Hvis du ikke kan vente så længe, ​​skal du læse Kyle Simpson's You Don't Know JS-bog på ES6 eller tjekke denne strålende lille hjemmeside!

Ønsker du at blive udvikler og få dit første softwarejob? Download de 7 trin til at blive udvikler og få dit første job.

NÆSTE -> Sådan sikres dit drømmejob. Lær interviewprocessen

Hvis du kunne lide dette og fandt det nyttigt, skal du vise din støtte ved at klappe væk og abonnere for at få flere artikler som denne!