Telerik blogs

In this article, we will look at how to write JavaScript code using some handy shorthands that make our code cleaner and easier to read.

JavaScript is a popular programming language for developing web applications and more. It has grown from a language used for creating simple scripts to make webpages to a dynamic one that can be used to create many programs.

We can make our JavaScript code cleaner by using some easy-to-read shorthands to do various operations—and that is what we will look at in this article.

The Ternary Operator (?)

The ternary operator lets us return a value if a condition is true and return a different value otherwise.

We can write an expression with it by writing a boolean expression, followed by ?, the value to return when the boolean expression returns a truthy value, : and the value returned when the boolean expression returns a falsy value.

For instance, we use it by writing:

const foo = true;
const bar = foo ? "heads" : "tails";
console.log(bar);

to return “heads” if foo returns a truthy value and “tails” otherwise.

As a result, bar is heads since foo is true, which is truthy.

This is the shorthand for it:

const foo = true;
let bar;
if (foo) {
  bar = "heads";
} else {
  bar = "tails";
}
console.log(bar);

As we can see, we simplified our code by replacing the if-else statements with a ternary expression.

We also avoided using let which is better since we won’t have to worry about reassigning a const variable to a new value by accident.

Optional Chaining Operator (?.)

The optional chaining operator lets us get properties that are deeply nested without worrying about any property in the chain not existing or having a non-object value.

The operator is denoted by ?..

For instance, we can use it by writing

const obj = {
  foo: {
    bar: {
      baz: {
        qux: 1,
      },
    },
  },
};
console.log(obj?.foo?.bar?.baz?.qux);

Then 1 is logged in the console log since obj?.foo?.bar?.baz?.qux property returns 1.

The benefit of this is that we don’t have to worry about any property in the chain not existing or having a non-object value.

For instance, we write:

const obj = {
  foo: {
    baz: {
      qux: 1,
    },
  },
};
console.log(obj?.foo?.bar?.baz?.qux);

Then the console log logs undefined since we no longer have the bar property in the obj object.

If we use the regular . operator to access the same property, we will get the bar property is undefined error since it doesn’t exist.

obj?.foo?.bar?.baz?.qux is equivalent to obj && obj.foo && obj.foo.bar && obj.foo.bar.baz && obj.foo.bar.baz.qux.

As we can see, the former expression is much shorter.

The optional chaining has been available since the ES2020 release.

Nullish Coalescing Operator (??)

The nullish coalescing operator is another operator that is introduced with ES2020.

It lets us return a fallback value if the value we want to return is null or undefined.

The operator is denoted by ??.

For instance, we use it by writing:

const foo = null;
const bar = foo ?? "bar";
console.log(bar);

const baz = undefined;
const qux = baz ?? "baz";
console.log(qux);

const x = 1;
const y = x ?? 2;
console.log(y);

If the first operand is null or undefined, then the second operand’s value is returned.

Therefore, bar is 'bar' and qux is 'baz'. y is 1 since x is 1, which is not null or undefined.

True Value Checks

If we want to check if an expression returns true, we don’t have to check for true with ===.

Instead, we just put the expression in the if statement.

For instance, instead of writing:

if (isHappy === true) {
  //...
}

We write:

if (isHappy) {
  //...
}

The first if statement only checks if isHappy is true.

And the second if statement checks if isHappy, returning a truthy value.

Therefore, if isHappy can return a truthy value other than true, then we may want to change the first if statement to check more precisely.

Default Parameter Values

Since ES2015, JavaScript functions can have default parameter values.

For instance, we write:

const add = (a = 1, b = 2) => {
  return a + b;
};
console.log(add(5, 6));

to set the default value of the a parameter to 1 and the default value of b to 2 in the add function.

This lets us set a fallback value in case any parameter has no value set.

Default function parameters if shorthand for something like:

const add = (a, b) => {
  if (!a) {
    a = 1;
  }

  if (!b) {
    b = -2;
  }
  return a + b;
};
console.log(add(5, 6));

where we assign a and b default values if they don’t have a truthy value.

As we can see, the first add function is much shorter than the second because of the use of the default function parameters feature.

Default function parameters are short and easy to understand.

For-of Loop

Oftentimes, we want to loop through every item in an array.

This can easily be done with the JavaScript for-of loop which has been available since ES2015.

We can use it by writing:

const arr = [1, 2, 3, 4, 5, 6];
for (const a of arr) {
  console.log(a);
}

to loop through the entries in the arr array with the for-of loop.

a is the loop variable that has the current entry in arr being looped through.

And we log the value of a in the loop.

Therefore, we see:

1
2
3
4
5
6

in the console log.

This is shorter than using a regular for loop where we have to define an index variable and use it to access the entry being looped through like:

const arr = [1, 2, 3, 4, 5, 6];
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

where i is the index variable that’s incremented by 1 with each iteration until it reaches arr.length - 1.

Another benefit of the for-of loop is that we can use it to iterate through any iterable object.

For instance, we write:

const set = new Set([1, 2, 1, 1, 4, 5, 6]);
for (const s of set) {
  console.log(s);
}

to loop through the set with the for-of loop.

s has the entry being looped through.

Since sets discard any duplicate entries when they’re added, we get:

1
2
4
5
6

from the console log.

Object Properties

We can add properties to an object by setting the object property’s value to a variable’s value.

For instance, we write

const x = 1;
const y = 2;
const obj = {
  x,
  y,
};
console.log(obj);

to create the obj object with properties x and y set to the values of variables x and y respectively.

As a result, we can see obj's value is:

{
  x: 1,
  y: 2
}

This is short for:

const x = 1;
const y = 2;
const obj = {
  x: x,
  y: y,
};
console.log(obj);

We can eliminate the colon and the expression after that if the property name is the same as the property value’s variable name.

This has been available since ES2015.

Exponents (**)

JavaScript has the exponentiation operator (**), which is equivalent to using the Math.pow method.

The left operator is the base and the right operand is the exponent.

For instance, we write:

const x = 2 ** 3;

to return the value of 2 raised to the power of 3 and assign that to x.

As a result x is 8.

We can do the same thing by writing:

const x = Math.pow(2, 3);

But ** is shorter and doesn’t involve calling any functions we don’t need to call.

Arrow Functions

Arrow functions let us define functions without using the function keyword.

It doesn’t bind to its own value of this so we can’t use them as constructor functions, which may be good depending on why we want to define the function.

If we don’t want to create an instance of the constructor, then we can use arrow functions.

For instance, we write:

const add = (a, b) => {
  return a + b;
};
console.log(add(1, 2));

to define the add function.

As we can see, we defined a function without using the function shorthand, which makes it shorter.

And since we don’t want to create a constructor function, where we manipulate the value of this, defining an arrow function is a good choice.

It is shorter than writing:

const add = function (a, b) {
  return a + b;
};

Template Literals

We can use the template literal location to define strings that can have expressions interpolated inside.

For instance, we write:

const numBottles = 100;
const str = `There are ${numBottles} bottles of beer on the wall.`;
console.log(str);

to interpolate the value of the numBottles variable in the string.

As a result, str is "There are 100 bottles of beer on the wall."

This is shorter than:

const numBottles = 100
const str = 'There are ' + numBottles + ' bottles of beer on the wall.`

which uses concatenation to put the value of numBottles into the string.

The template literal notation is better if we want to concatenate any strings and expressions together.

And it also preserves any spaces and newline characters that we add to the string, which is something that regular strings don’t have.

Destructuring Assignment

The destructuring assignment syntax is a handy shorthand introduced with ES2015.

It lets us assign object properties and array entries as the values of variables in one line.

For example, we write:

const arr = [1, 2, 3, 4, 5];
const [a, b, c] = arr;
console.log(a, b, c);

to assign the first three entries of arr to variables a, b and c respectively with the destructuring.

Therefore a is 1, b is 2 and c is 3.

This is much shorter than:

const arr = [1, 2, 3, 4, 5];
const a = arr[0];
const b = arr[1];
const c = arr[2];
console.log(a, b, c);

Since we have to use the index to get the value of the entries we want and then assign them to variables individually.

The destructuring syntax once again eliminates lots of repetition when we assign multiple array entries to as values of different variables.

The destructuring assignment syntax also works with object properties.

To use it with objects, we write:

const obj = {
  x: 1,
  y: 2,
  z: 3,
};
const { x, y, z } = obj;
console.log(x, y, z);

to get the values of the x, y and z properties in obj and assign them to the variables x, y and z respectively.

As a result, x is 1, y is 2 and z is 3.

This is much shorter than:

const obj = {
  x: 1,
  y: 2,
  z: 3,
};
const x = obj.x;
const y = obj.y;
const z = obj.z;

which gets the value of each property and assigns them to variables in their own lines.

The destructuring syntax once again eliminates lots of repetition.

Spread Operator (…)

The spread operator lets us copy array entries and object values.

For instance, we write:

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [...arr1, ...arr2];
console.log(arr3);

Then arr3 is [1, 2, 3, 4, 5, 6] since we copied the entries of arr1 and arr2 into the new array with the spread operator and assigned that as the value of arr3.

This is equivalent to:

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = arr1.concat(arr2);
console.log(arr3);

which also returned the merged version of arr1 and arr2 with arr1.concat.

To use the spread operator with objects, we write:

const obj1 = {
  a: 1,
  b: 2,
  c: 3,
};
const obj2 = {
  b: 4,
  c: 5,
  d: 6,
};
const obj3 = {
  ...obj1,
  ...obj2,
};
console.log(obj3);

to merge the properties of obj1 and obj2 into the same object and assign the merged object to obj3.

As a result, obj3 is:

{
  a: 1,
  b: 4,
  c: 5,
  d: 6
}

since properties b and c from obj2 override the values of the same properties in obj1 in the merged object because they’re merged in later.

d doesn’t exist in obj1 so it’s just copied over.

This is shorter than:

const obj1 = {
  a: 1,
  b: 2,
  c: 3,
};
const obj2 = {
  b: 4,
  c: 5,
  d: 6,
};
const obj3 = Object.assign({}, obj1, obj2);

which does the same thing but requires calling the Object.assign method, which is longer than the ... spread operator.

The spread operator also works with other iterable objects to spread iterable object entries into arrays.

We can use it by writing:

const arr = [...new Set([1, 2, 3])];

which copies the entries from the set iterable object into an array and assigns it to arr.

The spread operator for iterable objects has been available since ES2015 and the object spread operator since ES2018.

Conclusion

JavaScript is a popular programming language for developing web applications and more.

Many new JavaScript features since 2015 which helps us write JavaScript programs in a shorter and readable fashion. The ternary operator was even available before 2015.

These handy shorthands make our code cleaner and easier to read.


About the Author

John Au-Yeung

John Au-Yeung is a frontend developer with 6+ years of experience. He is an avid blogger (visit his site at https://thewebdev.info/) and the author of Vue.js 3 By Example.

Related Posts

Comments

Comments are disabled in preview mode.