Monday 2 September 2019

ES6 features in Lightning Web Components Part 1 - Variable Declarations

September 02, 2019 Posted by Sandeep , , , No comments
In December last year Salesforce announced to the world Lightning Web Components(LWC), a programming model that would make it easy for millions of JavaScript developers worldwide to code on the Lightning Platform. One of the main advantages of using LWC  is the support of ES6+ that would provide support for JavaScript features like classes, modules and import.

Like any excited developer I was inching to go through the documentation and see the capability of the framework.Salesforce documentation does a very good job to provide examples of creating numerous components on the Lightning Platform. Although while going through the documentation and examples, I came across various terms and bits of code that did not make much sense to me. A little more digging into these examples made me realise that some parts of code was using  ECMAScript 6 (or ES6) features that I rarely used while developing Aura Components.  Considering that LWC is the latest standard and are here to (hopefully :p) stay, I decided to understand the fundamentals of Modern JavaScript and ES6 Standards.

This series of posts will provide the foundation that a developer requires to understand modern Javascript standards and will also provide an introduction to new syntax and some awesome features to make out LWC code more modern, faster and more readable. Before we dive into the code of all the examples shown, I have tested all the code and it only requires LWC playground to compile.

Difference between var and let keywords

While both the keywords are used to declare variables in JavaScript, they behave quite differently. Have a look at the example below with var:
import { LightningElement, track } from 'lwc';
export default class VarLet extends LightningElement {
    connectedCallback(){
        var thisWillChange = 'String';
        var thisWillChange = 'Updated String';
        console.log(thisWillChange);
        // logs 'Updated String'
    }
}
In case you are not aware of what connectedCallback()  function does have a look at LWC documentation. While the problem shown above will be rarely faced in a small application, but as or code becomes larger(like it always does) we might accidentally override a  variable that was already being used.
Well this is not the only problem with 'var' keyword. We all love for loops (which we wont if we stick to these posts long enough!), if we declare the iterator as a var variable then it can be accessed outside the scope of that for loop. Have a look at the code snippet below and it's output
import { LightningElement, track } from 'lwc';
export default class VarFor extends LightningElement {
    connectedCallback(){
        for(var i=0; i<3; i ++){
            //loop logic here
        }
        console.log(i);
        //logs '3'
    }
}
We will try both the examples with let keyword instead.

Declaring the same variable with let keyword twice throws an error.
import { LightningElement, track } from 'lwc';
export default class LetOverride extends LightningElement {
    connectedCallback(){
        let thisWontChange = 'String';
        let thisWontChange = 'Updated String';
        //The above line will throw the error 
        //"Identifier 'thisWontChange' has already been declared (5:12)"
        console.log(thisWontChange);
    }
}
ReferenceError would occur if we try to access the iterating variable of a for loop if it is defined as a let variable. We will see the following output:

import { LightningElement, track } from 'lwc';
export default class LetFor extends LightningElement {
     connectedCallback(){
        for(let i=0; i<3; i ++){
            //loop logic here
        }
        console.log(i);
        //Throws a reference error that i is not defined 
    }
}

The const keyword

A variable assigned with const cannot be reassigned. In the below example reassigning the variable THIS_WONT_CHANGE gives an error.
import { LightningElement, track } from 'lwc';
export default class ConstEx1 extends LightningElement {
    connectedCallback(){
        const THIS_WONT_CHANGE = 'Sun rises in the east';
        THIS_WONT_CHANGE = 'Sun rises in the west';
        console.log(THIS_WONT_CHANGE);
        //Throws an error:
        //TypeError: Assignment to constant variable.
    }
}
As a best practice always declare constant variables as all uppercase letters.

Using const keyword with objects and arrays
There is one "gotcha" declaring objects and arrays as const. The const  keyword alone does not prevent  data from mutation. Which basically means that while we cannot completely reassign an object or an array but we can update the data inside the object or the array.
import { LightningElement, track } from 'lwc';
export default class ConstMutation extends LightningElement {
    connectedCallback(){
        const CONST_ARRAY = [1,2,3];
        //constArray = [2,3,4];
        //If above line is uncommented, it throws an error
        CONST_ARRAY[1] = 5;
        console.log(CONST_ARRAY);
        //logs [1,5,3]
    }
}
We can use the function Object.freeze to prevent a const keyword mutation.
import { LightningElement, track } from 'lwc';
export default class ConstMutation extends LightningElement {
    connectedCallback(){
        const CONST_ARRAY = [1,2,3];
        Object.freeze(CONST_ARRAY)
        CONST_ARRAY[1] = 5;
        console.log(CONST_ARRAY);
       //Throws a TypeError : Cannot assign to read only property 
      //'1' of object '[object Array]'
    }
}
In the next post I will cover arrow and Higher Order functions and how they can be implemented in Lightning Web Components.

0 comments:

Post a Comment