JS Hacks for Lazy Devs

Shortcuts for the initiated

Sean
4 min readNov 28, 2023

Number

Rather than going to the effort of typing the Number constructor you can just wrap a number (in parens) to access number functions…

Number(20).toFixed();
// lame!

20.toFixed();
// Error! (JS thinks this is a decimal)

(20).toFixed();
// thumbsup!

Also, the toFixed function is a quick way to make a number look like a price…

'£' + (20).toFixed(2);
// £20.00

Filtering

Can’t bothered to check if an item is undefined? You can pass the Boolean constructer straight into a filter call to do it for you…

['something', undefined, null, 3, 4].filter(Boolean).map(item => {
// Do whatever you like, item will never be null or undefined
});

This works because Boolean will return false if anything you give it is falsey. So Boolean(null), Boolean(undefined), Boolean(0) will all return false and get filtered out automatically.

Using join instead of the + operator

The plus sign can concat strings and even numbers but often it’s tricky to use if you’re not sure your values are defined or undefined:

let fullName = '';

// Rubbish, the fullName could show as "undefined Smith"
if (user.firstName || user.lastName) {
fullName = user.firstName + ' ' + user.lastName;
}

// Also rubbish, fullName could be " Smith"
if (user.firstName || user.lastName) {
fullName =
(user.firstName ? user.firstName : '') + ' ' + (user.lastName ? user.lastName : '');
}

// This works but...seriously? Rubbish
if (user.firstName || user.lastName) {
fullName =
(user.firstName ? user.firstName : '')
+ (user.lastName ? (' ' + user.lastName) : '');
}

Instead, use the filter trick with a join :

const fullName = [user.firstName, user.lastName]
.filter(Boolean)
.join(' ');

Using Includes the wrong way around

You often want to find if a string matches a set of values rather than just one:

if (
myString === 'case1'
|| myString === 'case2'
|| myString === 'case3'
) {
// Do stuff...
}

Rather than writing all these or conditions why not just invert an includes function to do it for you:

if (['case1', 'case2', 'case3'].includes(myString)) {
// Do stuff...
}

Ternary checks

Using an old version of Node without optional chaining but don’t want to waste time using extra if statements?

With optional chaining you’d just do this…

const propertyThatMightExist = myObject?.propertyThatMightExist;

Here’s the old school hack with better support…

const propertyThatMightExist = (myObject || {}).propertyThatMightExist;

You can also set a default with this method…

const propertyThatMightExist = 
(myObject || { propertyThatMightExist: 'cool' }).propertyThatMightExist;

Conditional properties

Want to add a property but only if it’s defined? Sometimes you don’t know if a value is defined and you don’t want to add the valued undefined if it’s not…

const myObj = {
value: myValueThatMightBeUndefined,
};

If myValueThatMightBeUndefined is undefined I don’t want the property value at all, so I might do something like this…

let myObj = {};
if (myValueThatMightBeUndefined) {
myObj.value = myValueThatMightBeUndefined;
}

But you can do this using a spread inside parens…

const myObject = {
...(myValueThatMightBeUndefined
? { value: myValueThatMightBeUndefined }
: {}
),
};

You can also do this using Object.assign

const myObject =
Object.assign(
{},
propertyThatMightExist && { value: myValueThatMightBeUndefined }
);

Higher Order Loops

Ever wanted to make a loop from a number but didn’t want other devs to think you’re a newb for using a for?

Try Array().fill():

Array(9).fill().map(() => {
// Loops 9 times...
});

Doing Array(9) makes an array with a length of 9, weirdly though it doesn’t fill the array with anything. So to make it useable you call fill afterwards.

Awaits with thens

This is sort of sacrilege but I often use then and catch in combination with an await because it allows me to handle errors without a try/catch block effecting the scope.

Here’s what I used to do:

let results;

try {
const { data } = await axios('/data');
results = data;
} catch (error) {
// I might want to ignore the error...
results = [];
}

I hate declaring the variable first, but I often have to because I won’t be able to use it outside the try block otherwise.

Here’s a much cleaner way of doing the same thing:

const results = await axios('/data')
.then(res => res?.data || [])
.catch(() => []);

I’ve basically reverted back to using the normal promise API here but the await lets me escape the functional style and keep things clear and linear.

This is also handy if you’re getting records but only want, say, the ids…

const userIds = await User.find()
.then(users => users?.map(u => u._id) || []);

--

--