DEV Community

Cover image for Top 5 JavaScript secrets
Arek Nawo
Arek Nawo

Posted on • Originally published at areknawo.com

Top 5 JavaScript secrets

JavaScript is a very... a very special language. Even when you think you know all its secrets, it can still surprise you.

Like most things in this World, not all of JS' secrets are really useful. In fact most of them aren't, as everything not well-known by others only leads to confusion. Using secret tips and tricks can make your code run faster or maybe even be smaller, but it'll certainly degrade its readability, which is bad for all the potential reader of your code - including yourself from the future.

But, with this little warning out of the way, there's nothing wrong with knowing these secrets - either to be able to read other's cryptic code, or just to show off.

So, without further ado, let's explore 5 of what I think are some of the least-known JavaScript secrets!

Void operator

Did you know that there's a void operator in JS? What does it do you might ask? Well, it takes an expression (either simple or complex one wrapped in ()) you provide right after it, evaluates it, and... always returns undefined.

void 0; // undefined
void "text"; // undefined
void {}; // undefined
void (() => {}); // undefined
// ... you get the point
Enter fullscreen mode Exit fullscreen mode

So, what kind of use-case is there for such a mind-boggling operator? Well, as it turns out - there's one. Believe it or not undefined can actually be defined!

(() => {
  const undefined = "foo";
  console.log(undefined, typeof undefined); // "foo", "string"
  console.log(void 0, typeof void 0); // undefined, "undefined"
})();
Enter fullscreen mode Exit fullscreen mode

For your information, in JS, undefined isn't a reserved keyword and can be used as a variable name, effectively overriding the global in a certain scope.

Using the void operator with random expression (usually 0) assures you that you'll get the proper unchanged undefined no matter what.

Optional parentheses

Parentheses are omnipresent in JavaScript - just as in almost any other programming language. But did you know that you don't have to always write them, even in places where you normally do?

Class constructor

The safest place to omit parentheses is in a parameter-less class constructor call. That's right - you can just remove your parentheses, save those 2 bytes of space, and have your code working just fine!

new Date();
new Date;
new Date().getYear();
(new Date).getYear(); // parentheses needed in a different place
Enter fullscreen mode Exit fullscreen mode

IIFE

The second and last (from what I know) place where you can omit parentheses is in IIFEs or Immediately-Invoked Function Expressions.

Typically, to use IIFE you need to wrap the function expression with parentheses and follow that with another pair of parentheses to actually call the function.

(() => {
  // ...
})();
(function () {
  // ...
})();
Enter fullscreen mode Exit fullscreen mode

But in reality, the wrapping parentheses aren't always required... at least under certain conditions. You can do so with function expressions defined with the function keyword and only when the IIFE result is being assigned to a variable or when it's preceded by an unary operator (like void, !, etc.).

void function () {
  // ...
}();
const result = function () {
  // ...
}();
Enter fullscreen mode Exit fullscreen mode

The operator or assignment is necessary so that the parser knows that the following function is actually a function expression.

Sadly, this method doesn't work with arrow functions, so if your goal is just to shave off some bytes, I suggest you use the arrow and discussed parentheses after all.

Comma operator

Next up we've got another operator - this time shorter and much more useful! It's a comma (,) - yeah, you've read that right - which in JS allows you to execute multiple expressions, one by one while "returning" the value retrieved from the last expression. Take a look:

// parentheses are required for proper assignment
const x = (1, 2, 3, 4); // 4
const y = ((() => "a")(), (() => "b")()); // "b"
const test = () => {
  return console.log(y), y;
};
test(); // logs "b" and returns "b"
Enter fullscreen mode Exit fullscreen mode

So, as you can see, the possibilities of the comma operator are truly impressive. You can use any expression and pretty much anything else with a little bit of help from the IIFEs. And when you combine that with arrow functions or console.log() for debugging you've got some impressively-short lambdas or better debugging experience without an additional line of code!

In operator

And while we're in the topic of operators, why not discuss yet another under-appreciated constructs from this category - the in operator. The only use-case for this operator is to check whether an object contains certain property, like so:

const obj = { a: 1, b: 2, c: 3 };
"a" in obj; // true
"d" in obj; // false
delete obj.a;
obj.b = undefined;
"a" in obj; // false
"b" in obj; // true
Enter fullscreen mode Exit fullscreen mode

So, why would you use a fancy operator, instead of simply checking for a property with an obj[prop] syntax like a normal person?

Well, there are some specific differences and thus advantages to this approach. First off, it's very convenient to use it for checking for the existence of properties that could hold falsy values. In such cases, typeof obj[prop] === "undefined" would be required, which is certainly much more verbose than "prop" in obj.

With that said, the drawback (or a feature depending on how you look at it) of the in operator is that it returns true even for properties that have been directly assigned the undefined value. If this is what you want, then I guess it's fine, but it also means that you'd have to use the delete operator to delete properties, instead of simply assigning undefined (which is a bit slower).

Labels

Lastly, we've got a feature that's also rarely used - labels. In JS, labels (like name:) can be used to effectively name blocks of code and different loop statements (e.g. for). Having such names assigned to specific parts of your code allows you to later reference these parts for use with statements like continue and break.

outer: for (let i = 0; i < 10; i++) {
  inner: for (let j = 0; j < 10; j++) {
    if (i === j) {
      continue outer;
    }
    console.log(i, j);
  }
}

block: {
  // Yup, code blocks are a thing
  console.log("You'll see this");
  break block; // You can break form code blocks when they're labelled
  console.log("But not that");
}
Enter fullscreen mode Exit fullscreen mode

Labels are especially useful when dealing with complex control flow within nested loops. Sure, you can use them to break out of code blocks, but I really don't know why would you do that - just use a functions or even IIFEs like a normal person.

Summary

So, that's my list of some of the most interesting and lesser-known JavaScript secrets. Let me know in the comments how many of these you did/didn't know about before reading this article. Oh, and also - if you like this kind of stuff, I highly encourage you to check out 2 of mine web dev tricks articles, and all the other stuff on this blog where I cover secrets of the Console API, Object API, and many more! Really cool stuff!

For more up-to-date web dev content, follow me on Twitter, Facebook, or through my personal blog. Thanks for reading and happy coding!

Top comments (7)

Collapse
 
bhagatparwinder profile image
Parwinder πŸ‘¨πŸ»β€πŸ’»

You said that we can omit parentheses in a parameter-less class constructor. This has gotchas.

new Date().toString() // works
new Date.toString() // fails

You addressed this in your blog post by saying

(new Date).getYear(); // parentheses needed in a different place

But why are those parentheses needed at a different place? Why doesn't it just work without parentheses? How will I remember that I need to use this confusing syntax?

 (new Date).getYear();

instead I could simply do

new Date().getYear();

This is what I am used to and it works.


Not giving you a hard time. There is a reason why you have to put the parentheses at a different place. It should be explained.

There is a reason why this works:

const x = new Date; // What I taught in this blog post
console.log(x.toString());

And this does not

new Date.toString();

It's because new Date.toString() is not equal to new Date().toString(). *There is an extremely subtle difference. They have different precedence. *

Check out: developer.mozilla.org/en-US/docs/W...

new Date.toString() throws an error because . has higher precedence than new Date so the expression becomes (or it is resolved as) (new (Date.toString))(). They might look the same but they are evaluated differently!

In short, if you would like to invoke the constructor and chain it with a method in the object, the correct syntax is:

(new Date).toString();
Collapse
 
koire profile image
Koire

I think this post should have a disclaimer at the top: "Please don't use this in production code"

On the other hand, void is useful when you are writing one-liners for hooks in React, because React will throw an error if you don't return a function or null:
useEffect(() => void setTimeout(myfunction, sometime))

Collapse
 
jsmanifest profile image
jsmanifest • Edited

void is also useful if you write switch statements like this:

switch (dataKey) {
  case 'hello':
    api.sortMyStuff()
    break
  case 'how are you':
    api.sortSomeoneElsesStuff()
    break
  default:
    break
}

You can reduce a couple of lines using them this way while maintaining the exact behavior:

switch (dataKey) {
  case 'hello':
    return void api.sortMyStuff()
  case 'how are you':
    return void api.sortSomeoneElsesStuff()
  default:
    return void
}
Collapse
 
bias profile image
Tobias Nickel

once I learned about labels, I thought they are so awesome, but since, i used them only twice, and one of those times was in go lang ☺

Collapse
 
i8sumpi profile image
Kira L

Wow! I have used the comma operator in python, but I never realized it worked in JavaScript! That's going to save a ton of space in my code now, thanks!

Collapse
 
janpauldahlke profile image
jan paul

I must agree with above comments. I learned about comma operator, which is nice :-) Ty for the writeup.

Collapse
 
pratham82 profile image
Prathamesh Mali

Known about iifes and comma operator but in operator looks great similar usage like python, great stuffπŸ‘