Quick ES6 Development Guide — Part 2

Updated: Apr 26

Quick ES6 Development Guide — Part 2

This post is part 2 of the series on ES6. It covers the technology section. If you have skipped part 1, you can view it on Medium. While the topics covered in this post are not related to part 1, reading part 1 first is recommended. In this post, we will discuss more ES6 features that are really useful. If you’ve mastered these, you can jump into Angular 2+ and React Native development. Let’s start!

Fat Arrow Functions If you are already using fat arrow functions in ES6, you know how easy and amazing they are. First, let’s take a look at a simple example using ES5: Anonymous function: a function that does not have a name. For example: setTimeout(function() { console.log('I am here after 3 light-years ;)'); }, 3000); Let’s give this anonymous function a name: function myFunction() { console.log('I am your function'); } setTimeout(myFunction, 3000); The above function has a name, myFunction. Notice the argument of the setTimeout function. We are passing a function as an argument because JavaScript functions are first-class functions. This means a function can take another function as its argument. ES6 introduced fat arrow functions, which is a slightly shorter way of writing anonymous functions. “An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.” — Mozilla docs Since arrow functions do not have their own this, the output is not similar to function expressions. Example: var compareObj= { age: 26, ageArrow: () => console.log(this.age, this), ageExpression: function() { console.log(this.age, this); } } > compareObj.ageArrow(); // undefined Window > compareObj.ageExpression(); // 26 {age: 26, ageArrow: ƒ, ageExpression: ƒ} The above setTimeout anonymous function could also be written using fat arrow function: Example one: setTimeout(() => { console.log("I am here after 3 light-years ;)"); }, 3000); Example two: Simple sum function legacy declaration and fat arrow representation. const sumFun = function(arg1, arg2, arg3) { return arg1 + arg2 + arg3; }; Fat arrow representation: const sumFun = ( arg1, arg2, arg3 ) => arg1 + arg2 + arg3; Or, in the case of multiline statements inside a function — you are required to return explicitly by using the return keyword, like in the following example. If it is a one-line statement, it is automatically returned (as stated in above example). const sumFun = ( arg1, arg2, arg3 ) => { return arg1 + arg2 + arg3; }

Destructuring Destructuring is a way to extract the values from an array and an object directly into variables. Let’s understand this with an example: const modusEmployee = { name: ‘Nikhil’, country: ‘India’, city: ‘New Delhi’, nativeLanguage: ‘Hindi’ }; In ES5, we could do object value extracting as: const empName = modusEmployee.name; // Nikhil const empCity = modusEmployee.city; // New Delhi In ES6, it is improved: const { name, city } = modusEmployee; console.log(name); // Nikhil console.log(city); // New Delhi Here, we are using an alias for the property name. const { name: empName, city: empCity } = modusEmployee; console.log(empName); // Nikhil console.log(empCity); // New Delhi Destructuring can be used in the following ways:

  • Object destructuring.

  • Array destructuring.

  • Function parameter destructuring.

We have already covered object destructuring, let’s see how array destructuring works. Array destructuring is quite similar to object destruction. The difference is that it extracts the values based on the index. const myCoins = [ 1,2,5,10 ]; const [ coin1, coin2 ] = myCoins; console.log(coin1) // 1 console.log(coin2); // 2 Bonus points If you just want the third value: const [ , , coin3 ] = myCoins; console.log(coin3); // 5; If you want all values in one variable: const [ ...all ] = myCoins; console.log(all); // [1,2,5,10] If you want to get the rest of the values: const myCoins = [ 1,2,5,10 ]; const [ coin1, ...otherCoins ] = myCoins; console.log(coin1); // 1 console.log(otherCoins); // [ 2, 5, 10 ] Handling conditions when no values are available for destructuring: default values. You can provide default values when the property you are destructuring is not defined: const [ random = ‘not found’ ] = [ ‘Available’ ]; console.log(random); // Availableconst [ random = ‘not found’ ] = []; console.log(random); // not found

Object Orientation: Class JavaScript is a prototype-based programming language and in ES5 there was no class keyword available to use. That does not mean that we couldn’t code using object-oriented programming in ES5. We can mimic object-oriented programming in ES5 by creating an object with prototype methods. Inheritance can also be achieved by using these objects. This is how we have had to create a class with ES5: var Automobile = function (engineSound) { this.engineSound = engineSound; } Automobile.prototype.engineSoundFun = function() { console.log(this.engineSound) };var enfield = new Automobile(‘dhuk dhuk’);enfield.engineSoundFun();Output: // dhuk dhuk If you are familiar with C++ or Java, you might be thinking: “Where is object orientation in the above example as no class keyword is used?” The syntax became easier to understand in ES6 as the classical object-oriented pattern in other languages. ES6 introduces the class keyword that makes it much easier to understand. ES6 Classes support prototype-based inheritance, super calls, instance and static methods, and constructors. Let’s do the above example in the ES6 way: class Automobile { constructor(engineSound) { this.engineSound = engineSound; } engineSoundFun() { console.log(this.engineSound); } }const enfield = new Automobile(‘Dhuk Dhuk’); enfield.engineSoundFun()Output: // Dhuk Dhuk Notice that the code is much cleaner, easier, and more familiar in ES6. However, the prototype pattern is still available to use in ES6.

Template Literals Remember, debugging code using console.log and variable concatenation: var name = ' Welcome! ' + first + ' ' + last + '.'; console.log(‘Hi ‘ + name + ‘ your username is ‘ + username): Luckily, in ES6 we can use a new syntax ${first} inside of the back-ticked string to clean it up: const name = ` Welcome! ${first} ${last}.`; console.log(`Hi ${name} your username is: ${username}`); Another issue before was using multiline strings, the new line statements used were printing with special characters like \n: var message = ‘Individuals in semler project \n are not just developers or testers, they are \n good friends’; Using a template literal with the back-tick now works as you would expect it to: const message = `Individuals in semler project are not just developers or testers, they are good friends`;

Spread Operator If you are aware of the concept of deep copy and shallow copy in JavaScript (take a glimpse below in the bonus section of this post), you can understand that, sometimes, it becomes hard to analyze what is happening between objects copying and their usage. Code speaks, let’s understand the scenario with an example (without the spread operator): const myCurrencyNotes = [1, 5, 10, 1000]; const piratedNotes = myCurrencyNotes;console.log(piratedNotes);Output: [1, 5, 10, 1000]> piratedNotes.push(50);console.log(piratedNotes);Output: [1, 5, 10, 1000, 50]Now, when you log:> console.log(myCurrencyNotes);Output: [1, 5, 10, 1000, 50] We know that when working with objects in JavaScript (arrays are a type of object), we assign by reference, not by value. It’s the same case with the usage of the spread operator: const myCurrencyNotes = [1, 5, 10, 1000]; const piratedNotes = [ ...myCurrencyNotes ];console.log(piratedNotes);Output: [1, 5, 10, 1000]> piratedNotes.push[50,100]> console.log(myCurrencyNotes);Output: [1, 5, 10, 1000] Spot the difference here, when we push elements in the piratedNotes array, the original array myCurrencyNotes is not affected. Another use case of spread would be: var newCurrencyNotes = [ 50,100 ]; var myAllCurrencyNotes = [ 1, 5, 10, newCurrencyNotes, 1000 ];console.log(myAllCurrencyNotes);Output:[1, 5, 10, Array(2), 1000].0:1 1:5 2:10 3:(2) [50, 100] 4:1000 You may not be expecting the third step in the output because it becomes a nested array. To eliminate such a problem we can utilize the spread operator: const myAllCurrencyNotes = [1, 5, 10, ...newCurrencyNotes, 1000] console.log(myAllCurrencyNotes);Output:[1, 5, 10, 50, 100, 1000] Spread in function: function checkFakeCurrencyNote(...notesVariations) { if (notesVariations.includes(1000)) { return ‘Contains an invalid currency denomination’; } else{ return ‘Aha! nice currency’; } }const currency = [ 1, 10, 1000 ]; > checkFakeCurrencyNote(...currency); Output: "Contains an invalid currency denomination"

Promise Objects are everywhere in JavaScript. A promise is also an object that returns its value in the future. Using a promise is useful when you have an asynchronous operation to perform. A promise can either be resolved or rejected. A promise in JavaScript is similar to our real-life promise. Suppose you invited your friend to a party (request sent) and they told you they may organize the party (resolve) or they may not (rejected). If a promise is called resolved, you can process it further using .then(). If the promise is rejected, it can be handled in a .catch() or as the second argument in a .then(). You can make a promise by using new Promise. This Promise constructor takes in a function that contains two arguments — resolve and reject. The basic skeleton for creating a Promise is: new Promise((resolve, reject) => { /* Do something here */ }); The promise is created with name promise, as we have already discussed above, in the case of .then() and error: promise.then((resolvedValue) => { console.log(resolvedValue); }, (error) => { console.log(error); }); Let’s understand this by taking a complete snippet: const yourAge = window.prompt(‘Enter your age’, 13); console.log(`Entered age is ${yourAge}`); The variable yourAge is declared and ready to store the user’s random input value in a browser prompt. We will use this random value later in the program: new Promise((resolve, reject) => { If ( yourAge < 99 ) { resolve("Congrats!! you are still young Carlos"); } else { reject(new Error(‘Now at this stage, you should start eating tons of veggies’)); } }); Here, I have initialized a promise using a new Promise and passed two arguments. The nested logic compares the variable yourAge value. If the value is less than 99, the promise returns resolve, otherwise, it rejects and outputs with an error. If we simply run the above snippet with a positive case value i.e value < 99, we will get nothing as output and if we provide a negative case value i.e value > 99, we will get an Uncaught error: Uncaught (in promise) Error: Now at this stage, you should start eating tons of veggies at Promise (:5:13) at new Promise () at :1:17 Note: Although you can remove new Error from reject and simply return a string like resolve, it is preferred to reject with an error but it is not required. reject(‘Now at this stage, you should start eating tons of veggies’); But, if your input is a negative case value, you will still get: Uncaught (in promise) Now at this stage, you should start eating tons of veggies These responses are expected. If you see the previous example above, we have to use .then and .catch to get the expected responses. promise.then((resolvedValue) => { console.log(resolvedValue); }, (error) => { console.log(error); }); Suppose you provided 89 as an input value, the output will be: Congrats!! you are still young CarlosPromise {: undefined} __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: undefined And for negative case input, suppose you provide 120: Now at this stage, you should start eating tons of veggiesPromise {: undefined} __proto__:Promise [[PromiseStatus]]:"resolved" [[PromiseValue]]:undefined

Bonus: Shallow and Deep Copy in JavaScript A shallow copy means the memory location of both objects will be the same. So, if you change the property value of the copy object, the property value of the original object will also change at a deep level of an object. A shallow copy will duplicate the top-level properties, but the nested object is shared between the original (source) and the copy (target). But, in deep copy, the memory locations will be different/separated. Changing the property values of copies object will not change the original one. Shallow copy example: The Object.assign() method is used to copy the values of properties from one or more source objects to a target object: let oldObj = { id:1 }> oldObj {id: 1} let newObj = { ...oldObj };> newObj {id: 1}> newObj.id = 9; > newObj {id: 9}> oldObj {id: 1} Everything is fine until here, but, as per the statement, “a shallow copy will duplicate the top-level properties.” Let’s understand this with an example: let oldObj = { a: 1, b: { c: 2, }, } let newObj = Object.assign({}, oldObj ); >newObj { a: 1, b: { c: 2} }oldObj.a = 10;> oldObj // { a: 10, b: { c: 2} }>newObj // { a: 1, b: { c: 2} }newObj.a = 20; >oldObj // { a: 10, b: { c: 2} }> newObj // { a: 20, b: { c: 2} }newObj.b.c = 30; > oldObj // { a: 10, b: { c: 30} }> newObj // { a: 20, b: { c: 30} } To solve this problem, we have a deep copy, check below. Thanks to my colleague, Mitchell, for simplifying this for me. Deep copy example: const oldObj = { id: 1, foo: { bar: 8 } };> const newObj = JSON.parse(JSON.stringify(oldObj)); > newObj.foo.bar = 10 // 10> oldObj.foo.bar; // 8

What’s Next I will update the link here of my upcoming post. There, we will learn how users can access your application even when they have low network connectivity or no network at all. I will share how your web application can load within three seconds (which is a performance benchmark criterion for a web application). I will also discuss how your web application can be used on a mobile device, like a hybrid mobile app with an app icon. So, stay tuned, there’s more to come. To gain a good understanding of ES6, I would recommend reading the first part of this topic. I hope this was a good read. Please share your feedback and suggestions. Happy coding!


Subscribe to Our Newsletter

© 2023 by BLIO

  • YouTube
  • Instagram
  • reddit-logo-newnew
  • medium-logo
  • LinkedIn
  • github-logo-new
  • Twitter
  • tiktok-logo-newnew
  • Facebook