DEV Community

NRF
NRF

Posted on • Updated on • Originally published at blog.bracketsinstitute.com

Explicit is better than tricks

When writing code, it is always better to be as explicit as possible instead of going for tricks. This concept is best explained by examples so let's get right into it.

The double bang !! (logical NOT)

This one is by far the most common "trick" in the JavaScript world. So much so that it is actually taught to developers as they learn about logical operators in JavaScript and can be found in Mozilla's official documentation (MDN). If you wish to obtain a primitive boolean (true or false) from a non-boolean entity, you can use the logical NOT operator as follows:

const primitiveBoolean = !!notABoolean;
Enter fullscreen mode Exit fullscreen mode

If notABoolean is truthy in the example above, primitiveBoolean will contain the value true and if it is falsy, primitiveBoolean will be false.

You can get the same results by using the Boolean() function and get a much more readable version of the code.

const primitiveBoolean = Boolean(notABoolean);
Enter fullscreen mode Exit fullscreen mode

Does the double bang way provide any benefit? The correct answer is no, but it does carry the disadvantage of making your code less readable. This trick (like many others) works because of JavaScript's type coercion. Let's look at the spec to see how the logical NOT operator (!) works.

spec for logical not operator

Specification for logical NOT operator

As can be seen, after the expression is evaluated and a final value is obtained, this final value is passed through an algorithm to get the final value's boolean equivalent. This algorithm is represented by ToBoolean() in the spec and is basically just a series of conditions to determine the boolean equivalent of a value (you can see the exact steps by clicking on ToBoolean on the spec's page). Once this is done, next step is what the NOT operator is supposed to do: return false if the evaluated value is true and true otherwise. The second NOT operator then inverts this value to finally give the correct result (and we end up with the double bang !!).

Now let's see how the Boolean() function works.

spec for boolean function

Specification for Boolean function

So when Boolean() is called as a function, as opposed to a constructor (i.e. with the new keyword), it performs a simple type conversion. This type conversion is done using the same algorithm, ToBoolean(), discussed above.

In both cases, your code is performing the same task behind the scenes. If anything, the double bang trick has an extra step of inverting the value obtained by the first operation. While using Boolean() results in a much more elegant and readable code.

The unary + operator

Wish to convert a string representation of a number to an actual number? Just precede it with a + like so:

const myData = +"123";
console.log(typeof myData); // output: "number"
Enter fullscreen mode Exit fullscreen mode

This gives us even more obscure code than the double bang trick discussed above. Still, this might prove to be controversial as even the MDN docs say that this is the "preferred" method to convert a string to a number. Let's look at the alternative:

const myData = Number("123");
console.log(typeof myData); // output: "number"
Enter fullscreen mode Exit fullscreen mode

Just as we had used Boolean() as a function to get a primitive boolean value, we have used Number() as a function here to convert the string to a number. The details behind the scenes here are exactly the same as before except the fact that instead of ToBoolean, the algorithm used for type conversion is called ToNumber in this case.

Specification for unary + operator

Specification for Number function

The MDN docs say that using the unary + operator is the fastest method but the specs tell us a different story. Both + and Number() use the exact same algorithm to do the type conversion but the latter results in a much more readable code.

The magic numbers

This one isn't related to type conversion but is seen relatively frequently. Magic numbers are the use of numbers directly in your code. It is more preferable to declare a well-named variable and assign it the desired value than to use the number directly.

if (password.length < 6) {
  throw new Error("Password must be more than 5 characters long");
}
Enter fullscreen mode Exit fullscreen mode

Considering the code above, a much better approach would be:

const MIN_PASSWORD_LENGTH = 6;

if (password.length < MIN_PASSWORD_LENGTH) {
  throw new Error(`Password must be more than ${MIN_PASSWORD_LENGTH - 1} characters long`);
}
Enter fullscreen mode Exit fullscreen mode

The first and obvious advantage here is that the code is now much more readable. Another potential advantage would be in the case where the same constraint is utilized in multiple places (which happens fairly often). If the constraint later changes, you'll only have to update it at one location.

If there is a direct number in your code, strongly consider declaring a constant and using it instead. Most of the times this will be the correct approach. Although there are some edge cases where using the number directly might be the preferable.

if (transactions.length > 0) {
  // show transactions
} else {
  // show msg: "No transactions"
}
Enter fullscreen mode Exit fullscreen mode

The above code is perfectly readable and there seems to be no reason to declare a separate variable for the value 0.

Conclusion

When writing code, readability should be a priority. The tricks/shortcuts usually add no benefit, performance or otherwise, and make the code considerably less readable. So, always go for a more explicit option.


πŸ‘‰πŸ» Subscribe to my newsletter: click here

πŸ‘‰πŸ» Follow me on twitter: click here


Discussion (14)

Collapse
lukeshiru profile image
Luke Shiru

I agree 100% ... every now and then you'll see post here in DEV with "tricks" that look like this: !!~~a | !~b which might be "clever", but you're definitely not thinking about your teammates or even your future self. One thing I would add is that casting in general is not great, and you should instead try to be more specific about what you want to test. Let's say notABoolean can be a given type or undefined, then:

const boolean1 = !!notABoolean; // πŸ’©
const boolean2 = Boolean(notABoolean); // πŸ™‚
const boolean3 = notABoolean !== undefined; // πŸŽ‰
Enter fullscreen mode Exit fullscreen mode

You're being clear about your intent, you don't actually want to do type casting, you just wanted to check if notABoolean is defined. Relying on falsy values is not ideal either, so this approach is also safer.

Something similar applies to number:

const number1 = +notANumber; // πŸ’©
const number2 = Number(notANumber); // πŸ™‚
const number3 = parseInt(notANumber, 10); // πŸŽ‰
Enter fullscreen mode Exit fullscreen mode

Here we wanted to do some parsing, but parseInt is a little bit safer than Number, and lets you defined the radix so you are able to convert hex, octal and so on.

Great post, btw! Good to see this kind of things here in DEV!

Cheers!

Collapse
nrf profile image
NRF Author

That is some quality input. Appreciated!

Just a side note about type casting. Kind of have to deal with it in JavaScript since all incoming data from the DOM is of type string!

Collapse
lukeshiru profile image
Luke Shiru

The DOM is nightmarish indeed, my point is mainly that we should avoid casting for stuff like "falsy" and try to use it only when is actually needed. If we want to check for an empty string, for example, you should do value === "" instead of !value.

Collapse
mistval profile image
Randall

I pretty much agree with this, but what is and isn't a trick is largely a matter of perception, and may change with time. Specifically, I remember learning !! to convert something to a boolean, and I didn't regard it as a trick. To me, it was just the way you convert something to a boolean. It's what I and the people around me did. I don't think I even knew about Boolean() then.

I think the perception that it's a fancy trick is one that has grown and become more common over time. Now I too regard it as one, and use Boolean() instead.

Collapse
nrf profile image
NRF Author

That is exactly what we wish to rectify.

Collapse
jonrandy profile image
Jon Randy • Edited on

Very bad idea. Will only drag down the quality of developers over time.

Teach people all about the language, don't blindly preach dogma and opinions. Show them the ins and outs of it, how it works, and different ways of doing the same things. Don't patronise them and treat them like children unable to make decisions about which way to do it is best for them or their project.

Readability is purely subjective, and marking parts of the language as 'off limits' or 'bad practice' inhibits knowledge, and potentially the performance of software.

It's this kind of thinking that has progressively dragged down and overcomplicated software over the past decade or more, particularly in web development.

Collapse
jonrandy profile image
Jon Randy • Edited on

A lot of the time, they do add performance benefit - and it can be considerable (a quick test showed !! to be consistently faster than Boolean - more than twice as fast in fact)

Collapse
aminya profile image
Amin Yahyaabadi • Edited on

Boolean is as fast as !!. Your test is not accurate.
github.com/solidjs/solid/pull/500#...

Collapse
jonrandy profile image
Jon Randy

Run this in both Chrome and Firefox. !! is faster in both, and on Firefox it is almost twice as fast

Thread Thread
jonrandy profile image
Jon Randy

If you want the simplest test possible, try this - not quite such a pronounced difference, but !! still faster

Thread Thread
aminya profile image
Amin Yahyaabadi • Edited on
Thread Thread
jonrandy profile image
Jon Randy • Edited on

Interesting. It's faster for me both on Mac, Linux, and Android - on both Firefox and Chrome

Collapse
moopet profile image
Ben Sinclair

I agree with all your points, but could you change the links to something more descriptive than, "click here"?

A screen reader listing links out will speak them all the same.

Collapse
nrf profile image
NRF Author

Thanks for highlighting this. I've updated the link texts.