JavaScript is the backbone of Lightning Web Components (LWC), and mastering key JavaScript concepts is crucial for Salesforce developers who want to build efficient, scalable LWCs. Here, we will see 12 must-know javascript concepts for LWC.
Let’s understand this must-know javascript concepts for LWC one by one along with code examples.
ES6+ javascript features
Arrow Function
Arrow functions are nothing but a shorthand syntax for writing traditional functions which is particularly useful in LWC.
// Normal function
connectedCallback() {
sortContactRecords() {
this.records.sort(function (Con1, Con2) {
return Con1.age - Con2.age; // Sort by age
});
console.log('Sorted Contacts:', this.records);
}
}
// Arrow function
connectedCallback() {
sortContactRecords() {
this.records.sort((Con1, Con2) => Con1.age - Con2.age); // Arrow fun. preserves 'this'
console.log('Sorted Records:', this.records);
}
}How is this useful in LWC:
- Arrow functions don’t bind ‘
this', which is important when dealing with component context in LWC - Many event handlers are arrow functions to keep the
thiscontext correct.
Destructuring
Destructuring allows unpacking values from arrays or properties from objects into different variables.
// Destructuring function parameters
handleContactUpdate({ detail: { id, name, email } }) {
// Use id, name, and email directly
this.updateContact(id, name, email);
}
// Array destructuring
const [firstName, lastName] = fullName.split(' ');
// Nested destructuring
const { contact: { Id, Name, Email } } = event.detail;How is this useful in LWC:
- It is useful in Event Handling & working with complex data structure in Apex
Spread & Rest Operator
The spread (...) operator can be used to expand arrays or objects, while the rest parameter syntax collects multiple elements into a single array.
// --------- Spread Operator -----------------------
// Creating a new array with additional items
const baseContacts = ['John', 'Jane'];
const allContacts = [...baseContacts, 'Mike', 'Sarah'];
// Copying arrays or objects (shallow copy)
const contactsCopy = [...this.contacts];
const contactDetailsCopy = { ...this.contactDetails };
//--------------Rest operator -------------------------
// Rest parameter in function definition
export function formatNames(firstContact, ...otherContacts) {
// firstContact is a single item
// otherContacts is an array of the remaining items
return firstContact.toUpperCase() + ', ' + otherContacts.join(', ');
}
// Rest pattern in destructuring
const [primary, secondary, ...remaining] = this.contactList;How is this useful in LWC:
- Handling variable number of parameters
- Copying arrays and objects
Array Functions
ES6 offers some amazing methods to manipulate array which makes working with List of data super easy in LWC
// 1.map() :- Creates a new array where each element is transformed by the provided function. let numbers = [1, 2, 3, 4, 5]; let squared = numbers.map(num => num * num); //uses arrow functions inside map console.log(squared); // [1, 4, 9, 16, 25] // 2.filter() :- Creates a new array with only the elements that match filter criteria. let numbers = [1, 2, 3, 4, 5, 6]; let evenNumbers = numbers.filter(num => num % 2 === 0); console.log(evenNumbers); // [2, 4, 6] // 3.reduce() :- Reduces the array to a single value by applying the function to each element. let numbers = [1, 2, 3, 4]; let sum = numbers.reduce((acc, num) => acc + num, 0); console.log(sum); // 10 // 4.forEach() :- Executes function on each array element but does not return a new array. let numbers = [1, 2, 3, 4]; numbers.forEach(num => console.log(num * 2)); // Output: 2, 4, 6, 8 (prints each number multiplied by 2) // 5.includes() :- checks if the array contains a certain element. let numbers = [1, 2, 3, 4, 5]; let hasThree = numbers.includes(3); console.log(hasThree); // true // 6.concat() :- combines arrays into one new array. let arr1 = [1, 2]; let arr2 = [3, 4]; let combined = arr1.concat(arr2); console.log(combined); // [1, 2, 3, 4]
How is this useful in LWC:
- All these methods are really useful in LWC for Data transformation, UI Interactions, Paginations and other efficient array operations.
Getter & Setter methods
Getters and Setters are special methods in javascript that allow us to define custom behaviour for accessing (getter) and modifying (setter) object properties. It can be very useful for data encapsulation, validation, and formatting.
import { LightningElement } from 'lwc';
export default class CartComponent extends LightningElement {
@api items = []; // Array to hold items
@track totalValue = 0; // Total value of items in the cart
// Getter for total value
get cartTotal() {
return this.items.reduce((total, item) => total + item.price, 0);
}
// Setter for adding item to cart
set addItem(item) {
if (item && item.name && item.price > 0) {
this.items = [...this.items, item]; // Add item to the cart
this.totalValue = this.cartTotal; // Update the total value
} else {
console.error('Invalid item');
}
}
// Method to handle adding item
handleAddItem(event) {
const newItem = {
name: event.target.name,
price: parseFloat(event.target.value),
};
this.addItem = newItem; // This triggers the setter
}
getCartMessage() {
return `Total Items: ${this.items.length}, Total Value: ${this.cartTotal}`;
}
}in above code we are using @track & @api reactive properties, understand use of @track vs @api decorators in LWC Here
How is this useful in LWC:
- Getter & Setter are specifically used for Encapsulation, Data Validation and getting dynamic values.
Default Parameters
Default parameters allow function parameters to have predefined values if no value or undefined is passed.
// in below function we title is default parameters
formatName(firstName, lastName = '', title = 'Mr./Ms.') {
return `${title} ${firstName} ${lastName}`.trim();
}
// Usage
this.formatName('John', 'Doe'); // "Mr./Ms. John Doe"
this.formatName('Jane', 'Smith', 'Dr.'); // "Dr. Jane Smith"
this.formatName('Alice'); // "Mr./Ms. Alice"How is this useful in LWC:
- Utility functions with optional configurations
- apex helper methods that can handle incomplete data
Promises & Asynchronous javascript
Promise
In LWC asynchronous operations (e.g. API calls, calling apex method) can take time to complete and execution can not wait until it finished. To manage these asynchronous operations smoothly, JavaScript provides a powerful tool: Promises.
It is an object that represents the eventual completion (or failure) of an asynchronous operation. It has three states : Pending, Fulfilled & Rejected. Once promise is returned, we handle its result in .then() for success and .catch() for errors as show below
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
export default class AccountList extends LightningElement {
@api accounts;
error;
connectedCallback() {
getAccounts()
.then(result => {
this.accounts = result;
this.error = undefined;
})
.catch(error => {
this.error = error;
this.accounts = undefined;
});
}
}How is this useful in LWC:
- Promises make handling Apex calls, data fetching, and other asynchronous tasks in LWC simpler and more intuitive.
@wireservice in LWC automatically handles the asynchronous nature of Apex call
Async/Await
Instead of chaining then() and catch(), we can also use the async/await syntax, which makes asynchronous code look more like synchronous code, and is often easier to read and write.
async is used to declare a function that will always return a Promise. Inside an async function, we use await to pause the execution of the function until the Promise resolves or rejects.
import { LightningElement } from 'lwc';
import getData from '@salesforce/apex/DataController.getData';
export default class AsyncAwaitExample extends LightningElement {
data;
error;
async handleFetchData() {
try {
// Using async/await with Apex
this.data = await getData(); // Awaiting the promise
} catch (error) {
this.error = error.body.message; // Handle error
}
}
}await is used to pause the execution of the code until the promise returned by getData() is resolved or rejected.
How is this useful in LWC:
- Async/await is more modern and allows for cleaner, more synchronous-looking code that is easier to manage and debug.
- Async/Await is better for working with a series of async operations in a more linear or sequential manner.
DOM manipulation
While working LWC, we often need to interact with the Document Object Model (DOM) to update the content or behaviour of front-end of our component. The DOM represents the structure of the page in a tree-like format, where each element (like paragraphs, divs, buttons, etc.) is a node in this tree.
DOM Manipulation is nothing but an interface so that using it programs can manipulate the structure, style, and content of the page dynamically.
In LWC, every component comes with a Shadow DOM. The Shadow DOM is like a private space where the component’s HTML and styles live, isolated from the global page. This helps ensure that your component doesn’t mess with the rest of the page’s layout or styles.
In JavaScript, we can use methods like document.getElementById() or querySelector() to find elements and change them. But in LWC, since we’re working with the Shadow DOM, things are a little different.
To manipulate elements in your LWC component, we use javaScript within the component’s class using this keyword. We can use :
this.template.querySelector(): This lets you find a single element inside your component.this.template.querySelectorAll(): This lets you find all elements inside your component that match a specific selector.
import { LightningElement } from 'lwc';
export default class ContactForm extends LightningElement {
// Query single element
focusNameInput() {
const nameInput = this.template.querySelector('.name-input');
if (nameInput) {
nameInput.focus();
}
}
// Query multiple elements and validate if fi
validateForm() {
const inputFields = this.template.querySelectorAll('.required');
let isValid = true;
inputFields.forEach(field => {
if (!field.reportValidity()) {
isValid = false;
}
});
return isValid;
}
// Get element by data attribute
getCityInput() {
return this.template.querySelector('[data-field="city"]');
}
}Events in Javascript
Events handling
In javascript, event handling is the process of responding to events that occur in our application. events can be things like User Interactions, Changes in data & External Interactions.
We listen for these events and react to them by triggering specific functions or actions. In LWC, we handle DOM events by attaching event listeners directly to elements in our LWC’s HTML template.
// myComponent.html
<template>
<lightning-button label="Click Me" onclick={handleClick}></lightning-button>
</template>
// myComponent.js
import { LightningElement } from 'lwc';
export default class EventHandlingExample extends LightningElement {
handleClick() {
console.log('Button clicked!');
}
} In above example:
<lightning-button>is a built-in LWC element that fires a click event when the button is clicked.onclick={handleClick}binds the button click event to thehandleClickmethod in the JavaScript file.
Custom Events
While standard DOM events are useful, sometimes we need to communicate between components—for example, sending data from a child component to a parent component. That’s where custom events come in
In LWC, we can create and dispatch custom events to send data or signal actions from one component to another.
//childComp.html
<template>
<lightning-button label="Send Message" onclick={handleSendMessage}></lightning-button>
</template>
//childComp.js
handleSendMessage() {
const messageEvent = new CustomEvent('message', {
detail: { message: 'Hello from child !' }
});
// Dispatch the event to the parent component
this.dispatchEvent(messageEvent);
}
//parentComp.html
<template>
<c-child-component onmessage={handleMessageReceived}></c-child-component>
<p>{receivedMessage}</p>
</template>
//parentComp.js
handleMessageReceived(event) {
// Extract the message data from the event
this.receivedMessage = event.detail.message;
console.log(this.receivedMessage);
}
}In this example:
- In child Comp, we created a custom event called ‘message’ & detail property contains all data we want to pass & then we dispatch this event
- In parent Comp, it listens for the ‘message’ event from child comp using ‘onmessage’ (on + custom event name).
- when parent comp is loaded, onmessage from child comp triggers
handleMessageReceivedmethod and there we can extract custom event details usingevent.detail
Local Storage & Session Storage
In JavaScript, localStorage and sessionStorage are both web storage mechanisms that allow you to store data on the client side (in the browser). They are part of the Web Storage API and help in saving data in key-value pairs in the browser.
In LWC, both are useful to save user preferences/session Data, store cache for performance and authentication tokens.
// Local Storage Methods
localStorage.setItem('username', 'PiyushLakhani'); // Save data to localStorage
let username = localStorage.getItem('username'); // retrieve data from localStorage
localStorage.removeItem('username'); // Remove a specific item from localStorage
localStorage.clear(); // Clear all items from localStorage
// Session Storage Methods similar to above
sessionStorage.setItem('sessionID', 'abc123');
let sessionID = sessionStorage.getItem('sessionID');
sessionStorage.removeItem('sessionID');
sessionStorage.clear();Key differences:
| Data Persistency | Data persists across browser sessions | Data only persists for the session (until the tab is closed) |
| Scope | Accessible from all tabs of the same origin | Accessible only from the same tab |
| User Case | Store data across sessions (e.g., user settings) | Store data for the duration of the session (e.g., shopping cart) |
Mastering these 12 must-know JavaScript concepts for LWC will surely boost your confidence when you will building your next Lightning Web Component (LWC).





Your means of explaining everything in this piece of writing is genuinely good, every
one be able to effortlessly know it, Thanks a lot
useful information, appreciated Thankyou
Thank you for the feedback ! Keep learning & growing