JavaScript Shorthand Coding Techniques

This article includes a round-up of some popular JavaScript shorthand coding techniques for beginners, which can be good for code optimization or minification purposes.

Assignment Operators Shorthand

Name Shorthand operator Meaning
Addition Assignment x += y x = x + y
Subtraction Assignment x -= y x = x - y
Multiplication Assignment x *= y x = x * y
Division Assignment x /= y x = x / y
Remainder Assignment x %= y x = x % y

Boolean Comparison Shorthand

The conventional way:

const value = true;

if (value === true) {
    // do something
}

The shortcut way:

const value = true;

if (value) {
    // do something
}

Get a Character From String Shorthand

The conventional way:

'string'.charAt(1); // output: t

The shortcut way:

'string'[1]; // output: t

Create a Link Shorthand

The conventional way:

const lnk = '<a href="https://www.google.com/">Google</a>';

The shortcut way:

const lnk = 'Google'.link('https://www.google.com/');

// output: <a href="https://www.google.com/">Google</a>

Although, the link() method has good browser support, still you should use it with caution as it is not a part of the standards, and may not work as expected in all browsers.

Create an Array Shorthand

The conventional way:

const people = new Array('john', 'jane');

The shortcut way:

const people = ['john', 'jane'];

Create an Object Shorthand

The conventional way:

const obj = new Object();
obj.a = 1;
obj.b = 2;
obj.c = 3;

The shortcut way:

const obj = {a: 1, b: 2, c: 3};

// use for loop to iterate over the properties of the object
for (let [key, value] of Object.entries(obj)) {
    console.log(`obj.${key} = ${value}`);
}

// output:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"

Please note that leaving a trailing comma before the closing curly brace can cause a problem in IE when declaring object properties.

Regular Expressions Testing Shorthand

The conventional way:

const pattern = new RegExp('world', 'i'); // case insensitive lookup

pattern.test('Hello World'); // output: true

The shortcut way:

/world/i.test('Hello World'); // output: true

Shorthand Using the Comma Operator

The comma operator evaluates each of its operands (from left-to-right) and returns the value of the last operand. This means that the following (and much more) is possible:

let i = 0;

do {
    console.log(i);
} while (i++, i < 4);

// output:
// 0
// 1
// 2
// 3

Consider another example where we process operands before returning. As stated, only the last operand will be returned but all others are going to be evaluated as well.

let a = 1;

function x() {
    return (a = 45, a += 1);
}

alert(x()); // output: 46

Using the Ternary (conditional) Operator

Common Usage:

The ternary operator is usually used as a shortcut for if else statement.

The conventional way:

if (cost > 10) {
    alert('Expensive');
} else {
    alert('Cheap');
}

The shortcut way:

alert((cost > 10) ? 'Expensive' : 'Cheap');

Other Usage:

Ternary operator can be used to shorten function calling. For example, conventionally if we do:

function add(item) {
    alert(`added: ${item}`);
}

function remove(item) {
    alert(`removed: ${item}`);
}

const inventory = 'low';
const product = 'shirt';

if (inventory === 'low') {
    add(product);
} else {
    remove(product);
}

// output: added: shirt

This can be re-written in a shorter way as:

function add(item) {
    alert(`added: ${item}`);
}

function remove(item) {
    alert(`removed: ${item}`);
}

const inventory = 'low';

((inventory === 'low') ? add : remove)('shirt');

// output: added: shirt

Similarly, we can use the same technique with objects to dynamically select a specific object property based on a condition, for example:

const inventory = 'low';
const stock = {
    add: function(item) {
        alert(`added: ${item}`);
    },
    remove: function(item) {
        alert(`removed: ${item}`);
    }
};

stock[(inventory === 'low') ? 'add' : 'remove']('shirt');

// output: added: shirt

Ternary evaluations can also be used to perform different operations, for example:

let stop = false;
const age = 16;

(age > 18) ? location.href('continue.html') : stop = true;

// output: stop = true

More than one operation can be evaluated as well for each case by grouping operations using () (brackets) and separating each one with a , (comma operator), like so:

let stop = false;
const age = 23;
	
const access = (age > 18)
    ? (
        alert('Allowed!'),
        'Access Granted!'
    ) : (
        stop = true,
        alert('Not Allowed!'),
        'Access Denied!'
    );

console.log(access); // output: Access Granted!

Remember that the comma operator evaluates all operands but returns only the last.

Shorthand Coding With Truthy and Falsy

In JavaScript, all values are truthy unless they are defined as falsy:

Truthy (values that evaluate to true):

if (true) // true
if ('0') // true
if ('string') // true
if ([]) // true
if ({}) // true
if (new Date()) // true
if (1) // true

Falsy (values that evaluate to false):

if (false) // false
if (0) // false
if (0.0) // false
if ("") // false
if ('') // false
if (``) // false
if (null) // false
if (undefined) // false
if (NaN) // false

Please note that there are a few other values (that are not very commonly used) that are considered falsy in JavaScript. If you wish to learn more about falsy values in JavaScript, then check out another post dedicated to that topic.

With that information, code like the following is possible:

let i = -5;
while (i++) {
    // runs till i = 0 since 0 is a falsy value
}

indexOf() Shorthand

String Contains:

The conventional way:

'string'.indexOf('ring') !== -1; // output: true

The shortcut way:

~'string'.indexOf('ring'); // output: -3 (which is a truthy value)

String Does Not Contain:

The conventional way:

'string'.indexOf('a') === -1; // output: true

The shortcut way:

~'string'.indexOf('a'); // output: 0 (which is a falsy value)

This works because ~ is a bitwise negation operator which inverts the binary digits of an operand. To make things simple, bitwise NOT-ing any number n yields -(n + 1). For example, ~5 yields -6. That means when indexOf returns -1 the bitwise negation of that (~-1) equals 0 which is falsy value in JavaScript, which makes the boolean evaluation equal false. This also means that all non-zero values would be truthy.

Type Casting Shorthands

Converting to Boolean:

By converting a value into strict Boolean data type, we can check whether it evaluates to truthy or falsy. A quick way to do this is to use the negation operator (!):

let a; // a = undefined

// if falsy (i.e. if false, 0, "", '', null, undefined, NaN)
if (!a) {
    // do something
}

Similarly, if we wanted to check if a value is non-falsy (or truthy), we could use the negation operator twice, like so:

const a = 1;

// if truthy
if (!!a) {
    // do something
}

Converting to Number:

The conventional way:

const num = parseInt('10');
console.log(typeof num); // output: number

The shortcut way:

const num = +'10'; // using the unary + operator
console.log(typeof num); // output: number

const num = -'10'; // using the unary - operator
console.log(typeof num); // output: number

The unary plus (+) operator precedes its operand and evaluates it, but attempts to convert it into a number if it isn't already. Although unary negation (-) can also convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number. It can convert string representations of integers and floats, as well as the non-string values such as true, false, and null.

// common scenarios with unary plus (+) operator
+3     // 3
+'3'   // 3
+true  // 1
+false // 0
+null  // 0
// common scenarios with unary negation (-) operator
-3     // -3
-'3'   // -3
-true  // -1
-false // -0
-null  // -0

Converting to String:

The conventional way:

const num = 10;
const str = String(num);

console.log(typeof str); // output: string

The shortcut way:

const num = 10;
const str = '' + num; // prefix (or suffix) empty string

console.log(typeof str); // output: string

It can convert integers and floats, as well as the non-string values such as 0, true, false, null, undefined, and NaN.

('' + 0);         // output: 0 (string)
('' + true);      // output: true (string)
('' + false);     // output: false (string)
('' + NaN);       // output: NaN (string)
('' + undefined); // output: undefined (string)
('' + null);      // output: null (string)

Self-Calling Anonymous Functions

Also known as Immediately Invoked Function Expression (IIEF), these are self-calling anonymous functions that execute automatically when the code is parsed by the browser for the first time. It has the following syntax:

(function(){
    // some code that will be executed automatically
})(); 

These anonymous functions can be useful to encapsulate code in its own namespace and protect code against variable name clashes.

This style of anonymous function wrapping is especially useful when working with multiple JavaScript libraries to avoid conflicting code. Consider the following example for jQuery JavaScript library:

(function($) {
    // some code that will be executed automatically
})(jQuery);

We pass the jQuery JavaScript object as an argument to the anonymous function, which allows us to use $ within the function expression without raising any potential conflicts with other code elsewhere in the document.

Other Syntax:

There are other ways to evaluate and directly call the function expression which, while different in syntax, behave the same way.

!function() {}();
+function() {}();
(function() {}());

Shorthand Coding by Short-Circuiting Evaluations

The boolean operators && (AND) and || (OR) perform short-circuited evaluation, which means when evaluating boolean operators, only as many arguments are evaluated as necessary to determine the outcome of a boolean expression.

As logical expressions are evaluated left-to-right, they are tested for possible "short-circuit" evaluation using the following rules:

  • false && (anything) is short-circuit evaluated to false.
  • true || (anything) is short-circuit evaluated to true.

For example, in the conjunction x && y, if x evaluates to false, the whole expression will be false, regardless of what the other argument evaluates to. Similarly, for a disjunction x || y, if the first argument evaluates to true, the whole expression will be true, regardless of what the other argument evaluates to. The following truth table illustrates this AND and OR boolean logic:

x y x && y x || y
false false false false
false true false true
true false false true
true true true true

With that knowledge, consider the following conventional code:

const count = null;

if (null !== count) {
    return count;
} else {
    return 1;
}

// output: 1

That can be re-written in a shorter way as such:

const count = null;

return count || 1; // output: 1

Keep in mind that the && and || logical operators in JavaScript themselves do not return a boolean value (true or false), but instead the value of the last operand they evaluate.

Therefore, the shorthand code above evaluates to 1 because count is null which is a falsy value, so the || (OR) logical operator moves to evaluate the second operand which is a truthy value 1.

Specifying Default Values:

Using short-circuiting technique can be a good way for specifying default values to variables:

function a(b) {
    // if the first operand is falsy, the default value is used
    b = b || 'hello world'; 
	
    console.log(b); // output: hello world
}

a(); // call function with no argument

You should note though, that all falsy values (which includes the number 0) will be evaluated as false. So, if in the code above, value of b was passed as the number 0 it would return the string "hello world" instead which might not be the result you expect in some cases.

Set Value If Truthy:

const a = 1;
const b = (a && a.toString());

console.log(b); // output: 1
console.log(typeof b); // output: string

The variable b would only be of type string if a is a truthy value. Consider the case below where a is undefined (falsy):

let a;
const b = (a && a.toString());

console.log(typeof b); // output: undefined

Eager (Non-Short-Circuited) Evaluations

There may be some instances where we may want to have non-short-circuited or eager evaluation, i.e. we would like to continue evaluating operands even if the first operand in the boolean conjunction x && y evaluates to false, or conversely the first boolean operand in the disjunction x || y evaluates to true.

In JavaScript, we could use the bitwise operators & and | which are eager, and yield identical truth tables:

x y x && y x & y x || y x | y
false false false 0 false 0
false true false 0 true 1
true false false 0 true 1
true true true 1 true 1

In the table you'll notice that & and | bitwise operators yield identical truth tables to the && and || logical operators, with the exception being that the result of short-circuited evaluation produces boolean values (true or false) while the result of the eager evaluation produces integer values (0 or 1).

The important difference to notice here is that the bitwise operators return 1 or 0. In order to conduct boolean evaluations, we need to convert them into strict boolean types. This is possible since the result of the bit-wise operators is identical to the truth tables of && and || logical operators. Therefore, we can simply type cast these into strict boolean types by using double not (!!) which would yield the following truth table:

x y x && y !!(x & y) x || y !!(x | y)
false false false false false false
false true false false true true
true false false false true true
true true true true true true

So, the main difference here is & and | do not do short-circuit evaluation in boolean expressions, which means:

  • While && will stop evaluating if the first operand is false, & won't.
  • While || will stop evaluating if the first operand is true, | won't.

This could be very useful, especially in cases where we want to evaluate all operands regardless of their boolean outcome. One such instance could be form validation, where we may not want to stop after encountering the first invalid field (which is what may happen in a short-circuited evaluation). We may instead want to validate all fields to highlight to the user all the invalid ones. Consider the following jQuery example:

HTML:

<form>
    <input type="text" id="name" name="name" />
    <input type="text" id="email" name="email" />
    <input type="text" id="msg" name="msg" />
	
    <input type="submit" />
</form>

jQuery:

const field1 = $('#name');
const field2 = $('#email');
const field3 = $('#msg');

function validate(field) {
    // check if field is invalid
    const isInvalid = (field.val() === '');
	
    // toggle invalid class using ternary operator
    field[((isInvalid) ? 'add' : 'remove') + 'Class']('invalid');
	
    // flipping isInvalid, returns true when field is valid
    return !isInvalid;
}

$('form').on('submit', function() {
    // do an eager evaluation of all fields
    const isValid = !!(validate(field1) & validate(field2) & validate(field3));

    // output result
    alert(isValid);
	
    // form is only submitted when all fields are valid (or truthy)
    return isValid;
});

The eager evaluation code helps us evaluate all fields and accordingly adds or removes the invalid class on all invalid fields. The form is only submitted when the conjunction is true.

The same example in short-circuited evaluation would have stopped after the first invalid field.


This post was published (and was last revised ) by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.