Original address:
Medium.freecodecamp.org/make-your-c…



Read more on the translator’s Blog:
Github.com/elevenbeans…

Template string

Template template strings make string concatenation easier than ever before. It starts with the reverse tag (the character right above Tab), and you can insert variables using ${variable}. Compare the following two lines of code:

123
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 }.`;Copy the code

This will make everything simpler and the code easier to read. You can put anything in curly braces: variables, equations, or function calls. I’ll use them in examples throughout this article.

Block-level scope

JavaScript itself has always been functional scoped, which is why we often wrap an entire JavaScript file in an empty call-immediate-function expression (IIFE). This is done to isolate all variables in the file, so there are no variable name conflicts globally.

Now we have block-level scope and two new variable declarations bound to the block.

Let

This is similar to VAR, but with some significant differences. Because the variables it declares have block-level scope, new local (internal) variables with the same name can be declared without affecting the external variables.

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

Because it is bound to a block (i.e., the range between {and}), it solves the classic interview question: “What is the output and how do you make it work the way you want it to?”

123
for (var i = 1; i < 5; i++){ setTimeout(() => { console.log(i); }, 1000); }Copy the code

In this case, it prints “5, 5, 5, 5” because the variable I is changed in each iteration, and everything ends up with the last change.

If you switch from var to let, that’s a different story. Each loop now creates a new block scope with the value bound to that loop. You write:

12345
{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)}Copy the code

Another difference between var and let is that let is not promoted like VAR.

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

Because of its stricter scoping and more predictable behavior, some have said that let should be used instead of VAR, unless declarations with VAR are specifically needed to enhance or require its looser scope.

Const

If you want to declare a constant variable in JavaScript, the convention is to name the variable in uppercase. However, this does not guarantee that it is a constant – it just lets other developers know that it is a constant and should not be changed.

Now we have a const declaration.

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

Const does not make a variable immutable, only locks its assignment. If you have a complex assignment (object or array), the value can still be modified.

12345678
{    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'}}Copy the code

Block-level scoping function problems

Function declarations are now specified that they must be bound to block-level scopes.

12345
{    bar(); // works    function bar() { /* do something */ }}bar();  // doesn't workCopy the code

The problem comes when you declare a function in an if statement.

Consider this:

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

Prior to ES6, both function declarations would have been enhanced, resulting in ‘I didn’t pass’, no matter what something was.

Now we get ‘ReferenceError’ because baz() is always bound by the block scope.

Extended operator

ES6 introduces… Operator, which is called the “extended operator.” It has two main uses: to split arrays or objects into new arrays or objects, and to combine multiple parameters into one array.

The first use case is the most you’re likely to encounter, so let’s look at it first.

12345678
let a = [3, 4, 5]; let b = [1, 2, ...a, 6]; console.log(b); // [1, 2, 3, 4, 5, 6]This can be very useful for passing in a set of variables to a function from an array.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=2Copy the code

You can also extend the object by entering each key-value pair into a new object. (It’s actually phase 4 of the proposal and will be officially launched in ES2018, only with Chrome 60 or later, Firefox 55 or later, and Node 6.4.0 or later)

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

. Another feature of the operator is that it creates a new array or object. The following example creates a new array for B, but C just points to the same array.

123456789
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 arrayCopy the code

The second example is to collect variables together into an array. This is useful when you don’t know how many variables are passed to the function.

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

Function default arguments

You can now define functions with default parameters. Missing or undefined values are initialized with default values. Just be careful – because null and false values are forced to be zero.

12345678
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 0Copy the code

Default values can be more than just values – they can also be expressions or functions.

1234567
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]Copy the code

deconstruction

Deconstruction is the process of breaking up the array or object to the left of the equals sign. Arrays or objects can come from variables, functions, or equations.

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

Object deconstruction lets you list the key of an object in braces to extract the key-value pair.

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

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.

Sometimes you want to take values and assign them to a new variable. This is done by pairing the key: variable to the left of the equals sign.

1234567891011
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.Copy the code

Another thing object deconstruction allows is to assign values to multiple variables.

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

Object literals and concise arguments

When you create object literals from variables, ES6 allows you to omit the key name if it is the same as the key and the variable name.

1234
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}Copy the code

This can also be used in conjunction with deconstruction to make your code simpler and cleaner.

123456789101112
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 parameterslet { name, age, job: {company}} = foo();Copy the code

It can also be used to deconstruct objects passed to functions. Methods 1 and 2 are how you do it before ES6, and method 3 uses deconstructed and concise parameters.

1234567891011121314151617181920212223
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 }.`); }Copy the code

With ES6, we can extract age, name, and company without additional variable declarations.

Dynamic property name

ES6 adds the ability to create or add attributes using dynamically allocated keys.

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

Arrow function

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

They can have a simpler structure than traditional functions because they don’t require function keywords, and they automatically return anything after the arrow.

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

If the function needs more than a simple calculation, curly braces can be used, and the function returns whatever the curly brace block scope returns.

12345
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}`; }Copy the code

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

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

In addition to having a shorter syntax, it also fixes problems that often occur in binding behavior. A fix with pre-ES6 functionality is to store this reference, usually as an argument.

12345678910
var clickController = {    doSomething: function (..) {        var self = this;        btn.addEventListener(            'click',            function() { self.doSomething(..) },            False       );   }};Copy the code

This must be done because the binding is dynamic. That means that this thing in this event listener and this thing in doSomething don’t refer to the same thing.

In the arrow function, the binding is lexical, not dynamic. This is the main design feature of the arrow function.

While this kind of binding can be great, sometimes it’s not desirable.

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

When we use a.onthing (6), the this.otherthing (b) reference fails because this does not point to an object, but to the surrounding scope. Be aware of this if you are rewriting legacy code using ES6 syntax.

The for… Of circulation

ES6 adds a way to iterate over each value in an array. This is different from the existing… In is different. It loops over key/index.

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

Using the new… 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.

Use the new for… Of loop, do not add a let val = a[idx] inside each loop.

Arrays, strings, generators, and collections can all be iterated over in standard JavaScript. A normal object cannot iterate unless you have defined an Iterator for it.

Numeric literal

ES5 code handles decimal and hexadecimal number formats well, but does not specify octal format. In fact, it’s banned under strict rules.

ES6 adds a new format that adds an O (note the letter) after the initial 0 to declare the number as octal. ES6 also adds a binary format.

12345
Number( 29 )  // 29Number( 035 ) // 35 in old octal form.Number( 0o35 ) // 29 in new octal formNumber( 0x1d ) // 29 in hexadecimalNumber( 0b11101 ) // 29 in binary formCopy the code

And a lot more…

ES6 gives us more features to make our code cleaner, shorter, easier to read and more powerful. My goal is to write a sequel to this article that covers lesser-known parts of ES6.