Useful JavaScript shorthand collection

Berkana
Bits and Pixels
Published in
10 min readMay 1, 2015

I enjoy writing and reading succinct code, and to that end, I would like to share with you some JavaScript ‘shorthand’ tricks that I’ve come across that you may find helpful for reducing the amount of code you have to write. This will be one in a series of posts; I will add to this as I find more.

Please note that there is a trade-off in using very terse shorthand: if the shorthand is very unconventional, it may not be as easy to read. I would like to propagate the use of these shorthand forms as new conventions, but until these become popular, there is a risk that your code will be more difficult for others to understand and maintain.

In each of the following examples, the long form is shown on the left, and the short form is shown on the right.

1. Converting the arguments object into an array

The arguments object in JavaScript functions does not have many of the useful methods that are built into native JavaScript arrays. Converting the arguments object into an array is a task that is done frequently enough that we should all be familiar with the way it is done.

Converting the arguments array-like object into an array is usually done to enable the use of methods that are available to native arrays.

This works because an empty array literal has access to the slice method, which you can call on arguments. By using an empty array literal rather than Array.prototype, you save 13 characters. However, this is unconventional enough that it may cause confusion, since the long form is widely mentioned in search results on how to convert the arguments array-like object into a native array.

Update: this trick apparently kills optimization

It turns out that (as of the writing of this update) passing arguments to any other function kills the JavaScript optimization process in V8, the JavaScript engine used in Node and in Chrome. The optimization can add considerable speed to your code, so if you’re at the stage where you’re optimizing your code, you may want to replace the .slice.call(arguments) code with the following, which will not de-activate optimization.

function doesntLeakArguments() {
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {
//i is always valid index in the arguments object
args[i] = arguments[i];
}
// use args as you would use an array of the arguments.}

The reasons for why the optimizer will not attempt to optimize code that passes arguments into another function or returns it out of a function is beyond the scope of this article, but if you want to understand why and learn about other optimization killers, take a look at this article: Optimization Killers.

Not surprisingly, this is a trade-off between simplicity and performance; the simple form will likely help you get your solution coded faster, but the verbose form shown above should be substituted in when you are ready to deploy your code, to achieve optimal performance.

2. Use a countdown while-loop instead of a for-loop

One of my preferred techniques of writing less code is to use the .forEach() and .map() methods rather than to use a for loop to iterate through an array. But in instances where .forEach() or .map() are not appropriate, using a while loop to carry out iteration results in less visual clutter.

A count-down while-loop is cleaner and more succinct than a for-loop, and can be substituted for the equivalent effect in most cases.

The while-loop form eliminates the code setting up the initial condition and while merging the count code and the truth condition into one expression. It is also worth noting that assigning array.length to a variable once and using the stored variable is slightly more performant than looking it up on every single iteration, since length appears to calculated.

3. Use a for-in loop even with arrays

The for-in loop construction is commonly prescribed for looping over the enumerable properties of objects, but it also works for arrays, and has cleaner looking code than the basic for-loop. The official caveat is that for-in loops are not guaranteed to loop through the array in a consistent order, but I have personally never run into a case where this has happened. If all you care about is that all the items in an array are operated on, and the order in which they are operated on does not matter, a for-in loop will suffice and give you cleaner looking code. Caution: the for-in loop will also loop over any enumerable properties that have been added to the array, and not just the numeric indices; if you don’t want this, don’t use this short-hand.

4. Type coercion of a value into a boolean

There have been a few occasions where I needed to coerce a value into a boolean value. Here’s the straight-forward way, along with the shorthand form that has the equivalent effect.

Double-negation has the same effect as using Boolean() to cast an expression into a boolean value.

The double-negation works for type-casting because negating any value casts it into a boolean value of the opposite sense —i.e., negating a truthy value returns false; negating a falsy value returns true. Negating that value again only negates the sense, while still returning a boolean. As with many of these shorthand forms, the risk is that the code may be harder for a novice to read.

5. A brilliant and terse equivalent to Math.floor()

I came across this brilliant but terse way to round any number down to the nearest lesser integer:

Double bitwise NOT has the same effect as Math.floor() for positive numbers and Math.ceil() for negative numbers.

Those double bitwise negation has the effect of rounding a number towards zero; it behaves like Math.floor() for positive numbers, and Math.ceil() for negative numbers. The explanation for why this works can be found here; this one is arcane enough that I cannot easily explain why it works, but it is both performant and terse. Until this technique is more commonly known, this one is definitely at risk of being mis-read by others trying to maintain your code. But, it saves you ten characters, which is nice.

Digression: the use of Math.floor()

In my own practice, my most common use of Math.floor() is in the function for generating random integers. For those of you who are not familiar with the code for generating a random integer, here it is, in standard form:

This is the function for generating a random integer.

The Math.random() method returns a random decimal number, which we scale to the range we want by multiplying it by upperBound. We then round it down to the nearest lesser integer using Math.floor() to obtain our random integer.

6. Characters access using array notation on strings.

Strings can have the element in at a given position retrieved using the same notation used to retrieve items from an array rather than using the .charAt() method, saving you seven characters.

7. Clever shorthand for true and false, but not recommended.

This works because 0 is falsy, and 1 is truthy; negating them results behaves like a sort of type-coercion combined with sense inversion.

For once, I’m going to recommend that you not use this shorthand. It involves more calculation, adds confusion, and doesn’t save enough characters to be worth the obfuscation. However, it is rather clever. Maybe if you need some snippet of code to be as terse as possible, or if you have a huge app that uses boolean values so many times that every last character counts, this will prove to be useful.

8. The conditional operator and neat tricks it can do

If you aren’t familiar with the conditional operator, here it is:

In fact, this operator can even be spread across multiple lines, and shouldn’t cause confusion among those maintaining your code if they are competent at JavaScript. The one thing to watch out for is that multiple expressions are to be separated by commas rather than semicolons when using this operator:

One key feature of the conditional operator is that it returns a value, as can be seen in the first example for this operator. The last statement in the parenthesis-enclosed block that gets executed becomes the return value of the whole operator. If it happens to be a function, the function that gets returned can be called immediately. This enables you to use terse notation such as this for calling one of two functions according to the outcome of a condition:

9. Using the logical AND operator as a conditional

The logical AND operator executes the first statement, and only if it is true, executes the second statement, and returns its value, which is often used for its truth value. This can be used as a terse substitute for the conditional operator.

You can even combine this with a logical OR for the equivalent of an if-else statement. However, if you’re going to do that, it’s not really saving you many characters, and is often not worth the confusion. However, it could also be said that if you’re going to save characters, the if statement doesn’t require braces around the statement if it is the only statement that is part of the conditional, and if it is short, you can just write it all on one line. However, leaving off the braces is usually contrary to the style guides required by most companies.

10. Coercing a string into a number

Here’s my latest addition to this collection:

// long form
var example1 = parseFloat("12536"); // for floating point number
var example2 = parseInt("12546", 10); // for integer number
// Short form
var example3 = +"12536";

In this example, a string that represents a number is being converted into a number. If you use parseInt, you need to specify the number base as the second argument. But JavaScript’s handling of number types is not very explicitly as it is in languages such as C, and if you don’t specifically need an integer or a floating point number, simply prepending + will convert it to a number. I tested this out on a JavaScript interpreter, and it seems to turn strings that represent integers into integers, and strings that represent floating point numbers into floating point numbers.

When would you ever need to coerce strings into numbers? I know of at least a couple of cases. One problem I solved required appending digits to a prefix to form a number, but appending is a string operation, not a number operation. The solution was to do all the appending in string format, and to coerce the string into a number once all the string operations were done. Also, if you have to extract a number from a string and use it, coercing the number-string you extracted will require this kind of operation.

11. Coercing a number to a string

Just as you may need to coerce a string to a number, you may need to coerce a number to a string representing the number. The formal way of doing this is as follows:

var example = 3.14;
var string = example.toString(10);
// '3.14'
// the argument to the toString method is optional; it's the base
// you want for the resulting number.

There is, however, a simpler way to coerce a number to a string. When adding a number to a string, the JavaScript interpreter will take the number and coerce it to a string and concatenate the two. Knowing this effect, you can simply add a number literal to an empty string, and the outcome of that operation will be the string of those digits:

var demo = 1234+'';
// demo is now equal to '1234'
example +='';
// example now is '3.14'

There is no need to put the number in a variable to invoke the toString() method. In most cases, I find that when I need to convert a number to a string, I need it to be in base 10, which seems to be the default. If you need a different number base, such as hexadecimal, octal, or binary, then you should use the toString() method that is built into numbers.

Based on playing around with this on a JavaScript interpreter, number literals don’t work with this trick; the number seems to have to be stored in a variable before the toString() method is used on it, but the coercion shorthand will return a string just fine even when used on number literals.

12. Test for the results of failed look-ups

Often you’ll find that built-in methods such as indexOf() will return -1 when the item for which you’re looking up the index isn’t found in the string or array at hand. In this case, the fact that the number 0 is considered falsy may be a source of confusion, since 0 is a perfectly valid index number. Commonly, I see the following code used to test for the non-presence of an item:

// test if an item IS found in an arrayif(array.indexOf(item) >= -1){
...
}
// test if an item IS NOT found in an arrayif(array.indexOf(item) === -1){
...
}

There is a shorter expression of this:

// test if an item IS found in an arrayif(~array.indexOf(item)){
...
}
// test if an item IS NOT found in an arrayif(!~array.indexOf(item)){
...
}

The ~ operator will return a truthy value for anything but -1, and !~ will do the oposite.

Because this is trick is terse and likely not commonly known, for the sake of clarity, I recommend setting an appropriately named variable that indicates the intention, and testing that variable.

var found = ~array.indexOf(item);if(found){
...
}

The verbose way of testing for -1 may be more commonly known, but it also fails to communicate intention. However, if you set a variable to indicate your intention, you’re not saving any characters by using this shorthand. This is a trade-off that will never quite go away. For the sake of maintainability, err on the side of clarity.

--

--