LogoLoading Please Wait...

JavaScript’s Shorthand Syntax That Useful to Developer

By divine_admin_infosys

JavaScript is the native, natural, and productive way to create dynamic pages for all standard web browsers. Nowadays, JavaScript is everywhere — we can use it for building web services, desktop apps, mobile apps, CLI programs, and embedded systems. With this popularity, the ECMAScript standard introduces new language features for JavaScript to boost developers’ productivity further.

In this story, I’ll explain several modern JavaScript syntaxes you can practice in any JavaScript-based codebase to write futuristic, minimal, highly-readable, and clean source code!

Using the Spread Syntax

As the name suggests, the spread syntax helps us to convert objects, iterable objects, such as arrays, sets, etc., into separate individual records. So, we can use this feature to construct new data structures based on existing data structures and pass iterable objects to functions as individual parameters. The spread syntax typically helps you to avoid verbose loop structures and make your source code more futuristic, readable, and self-explanatory. Let’s check several practical examples!

Before the ES6 spread syntax, we used the arguments object to implement dynamic parameter counts in functions:

function sum() {
    return Array
            .from(arguments)
            .reduce((acc, x) => acc + x);
}

console.log(sum(10, 20, 30));     // 60

The spread syntax can simplify the above code snippet further as follows:

function sum(...args) {
    return args.reduce((acc, x) => acc + x);
}

console.log(sum(10, 20, 30));      // 60

In this example, the spread syntax even made the function definition more readable since the sum function had zero parameters without the spread syntax before.

Modern developers frequently use the spread syntax to create/copy objects and arrays:

let numbers = [10, 20];
let letters = ['a', 'b'];

console.log([...numbers, ...letters]);  // [ 10, 20, 'a', 'b' ]

let doc = {id: 100, title: 'new'};
console.log({...doc, copies: 2}); // { id: 100, title: 'new', copies: 2 }

The spread operator works with any object that implements the iterable protocol:

console.log([...new Set([2, 5])]);        // [ 2, 5 ]
console.log([..."aeiou"]);                // [ 'a', 'e', 'i', 'o', 'u' ]
console.log([...new Map([[0, 'a']])]);    // [ [ 0, 'a' ] ]

Inline Short-Circuits and Nullish Coalescing

Inline short-circuit evaluation techniques help us to avoid verbose if conditions that typically set default values. The traditional if condition first comes to our mind for any conditional programming requirement, but it doesn’t make every use of it effective and smart.

Look at the following code snippet:

function printDoc(doc) {
    if(!doc.title)
        doc.title = 'Untitled';
    console.log(doc);   // { id: 200, title: 'Untitled' }
    // ...
}

printDoc({id: 200});

Here we can use an inline short-circuit || to simplify:

function printDoc(doc) {
    doc.title = doc.title || 'Untitled';

    console.log(doc);   // { id: 200, title: 'Untitled' }
    // ...
}

printDoc({id: 200});

The || operator sets the second value only if the first value evaluates to false. Similarly, it’s possible to use the && boolean operator to set the second value when the first value evaluates to true. JavaScript treats 0 and an empty string as false in the boolean context, so we need to be careful while using short circuits in some situations.

For example, the following statement will never print 0:

let doc = {id: 0};
console.log(doc.id || 200);   // 200

This situation can make bugs in frontends that rely on RESTful APIs that often output 0 as a valid property value and output null when a specific value isn’t set. The nullish coalescing operator sets the right-hand value only if the first value is null or undefined:

let doc = {id: 0};
console.log(doc.id ?? 200);   // 0

The Exponentiation Operator and Assignment

Every programming language offers standard mathematical functions via its standard APIs. JavaScript has a pre-imported mathematical module in both the browser environment and Node.js. For exponentiation, we can use the Math.pow inbuilt function with the base and exponent.

The ES7 exponentiation operator (**) offers the same feature that the Math.pow function provides, but with a better language grammar as follows:

console.log(2 ** 2);   // 4
console.log(2 ** 10);  // 1024

This is an excellent feature for full-stack developers who use Python backend services since Python had this syntax from its inception. Similar to Python, ** has higher precedence over * (multiplication):

console.log(2 ** 5 * 2);   // 64
console.log((2 ** 5) * 2); // 64

The exponentiation assignment also works the same as other assignment operators in JavaScript:

let n = 2;
n **= 2;
console.log(n);  // 4

Optional Chaining for Better Readability

Nowadays, web developers tend to build web applications that fetch data from RESTful-based-like web services. These web services typically use JSON structures for communication, so programmers usually access nested data records by using the . symbol. In some scenarios, they use nested data objects to transfer data between functions and modules. They even use callback functions inside complex objects.

The traditional . symbol is a good technique, but it often leads to one of the most common (and critical) mistakes or bugs in JavaScript-based development: TypeErrors.

For example, the following code snippet triggers a bug when the assignee property is not set (becomes undefined):

let task1 = {
    id: 101,
    title: 'check attendance',
    time: '10:50',
    assignee: {
       id: 50,
       name: 'John'
    }
};

let task2 = {
    id: 102,
    title: 'read agenda',
    time: '11:00'
}

function showAssignee(task) {
    let msg = `Assignee: ${task.assignee.name}`;
    console.log(msg);
}

showAssignee(task1); // Assignee: John
showAssignee(task2); // TypeError!

The second showAssignee function call throws an error since the assignee field is undefined. In the past, we solved these undefined property-related issues with short-circuits, ternary operators, and if conditions:

// With ?:
function showAssignee(task) {
    let name = task.assignee ? task.assignee.name : 'Nobody';
    let msg = `Assignee: ${name}`;
    console.log(msg);
}

// With && and || (short-circuits)
function showAssignee(task) {
    let name = (task.assignee && task.assignee.name) || 'Nobody';
    let msg = `Assignee: ${name}`;
    console.log(msg);
}

// With if
function showAssignee(task) {
    let name = 'Nobody';
    if(task.assignee)
        name = task.assignee.name;
    let msg = `Assignee: ${name}`;
    console.log(msg);
}

Now, the modern optional chaining syntax helps us to avoid nested property existence checks with ?.:

let name = task.assignee?.name || 'Nobody';

This syntax becomes very helpful for minimizing code complexity since it returns undefined when a property doesn’t exist instead of throwing a TypeError instance. So, you may write task.assignee?.address?.postalCode instead of two undefined property checks!

 

Non-Decimal Number Representation

Let’s start this section with a question. Do you think that the following console.log statements output the same number?

console.log(10);
console.log(010);

Some developers will say both outputs 10 assuming that the leading zero does not affect most programming languages’ number literals. In most languages (including JavaScript), octal number literals start with a leading zero. So, the second console.log statement prints 8 (converted decimal value of octal10) — not just10.

This leading zero strategy is deprecated in the JavaScript strict mode, so we should use the standard approach: the 0o prefix:

console.log(0o10);

JavaScript number literals also support binary and hexadecimal prefixes, as shown in the following example code snippet:

console.log(0b101); // 5
console.log(0xee);  // 238

These inbuilt non-decimal literals are helpful when we work with Unix file permissions, color codes, and computer science-related applications. The great thing is that JavaScript automatically converts non-decimals when you print them on the console or process them with decimals:

console.log(0b101 + 5); // 5 + 5 -> 10
console.log(0b111 === 7) // 7 === 7 -> true


Destructuring and Multiple Assignments

The ES6 standard came with the destructuring technique to help JavaScript developers to extract values from objects and arrays. The object destructuring technique typically supports us to unpack values from complex objects, as shown in the following example:

let doc = {
    id: 110,
    title: 'Untitled',
    copies: 20,
    paper: 'A4',
    data: {
        file: 'doc_110.bin',
        format: 'pdf'
    }
};

let { id, title, data: { file } } = doc;

console.log(id, title, file); // 110 Untitled doc_110.bin

The array destructuring syntax looks the same as the multiple assignment syntax in Python. But, in Python, the multiple assignment syntax is strict and must match the array length, so we often use the _ identifier to match the array length by unpacking unused records.

In JavaScript, destructuring-based multiple assignments are so flexible, and you don’t need to use unnamed identifiers for array records that you don’t need to unpack:

let A = [1, 2, 10];
let [a, b] = A;

console.log(a, b); // 1 2

Similar to Python’s * list prefix, we can use the spread syntax to save the rest of the array records while unpacking:

let A = [1, 2, 10];
let [a, ...rest] = A;

console.log(a); // 1
console.log(rest); // [2, 10]

 

Divine Infosys