- 4 minutes read

Never use .constructor.name in production code unless you like working long hours! I know from experience because that's what we did the other day. But wait - are you already familiar with the constructor.name idiom? It's tremendously useful. I'm using it almost every day for debugging.

Tell me who you are!

JavaScript is an anarchist language. It uses dynamic typing. In other words, you never know which kinds of objects you're dealing with. Countless times I've observed JavaScript programmers being 100% sure they were dealing with, say, objects of type "dog" only to learn the object is something else entirely. JavaScript is flexible enough to let Plant objects pass as Dogs. So I've learned to check the type of objects I'm dealing with frequently. Just printing the object in the console window hardly ever does the trick. You'll learn a lot about the value of the object but little about its class.

That's not surprising because there's no such thing as a class in JavaScript. It's all objects and prototypes, at least in older JavaScript versions. However, I'm using either TypeScript or modern JavaScript versions most of the time, so talking about "classes" isn't entirely wrong.

And that's where .constructor.name comes in handy. Enter the name of a variable in the debugger of Brave, Chrome, or Firefox, hit enter, and you'll see the value of the object. Add .constructor.name to the variable name, and you'll see the name of the class of the object. Awesome!

Avoid using .constructor.name in your sourcecode

You should just avoid using this idiom in your source code. It's tempting to write code like this:

function howToMakeHappy(being: Dog | Oak): string if (being.constructor.name === "Dog") { return "walk it"; } else { return "water it"; }

That's great. It's just it's going to fail in production. Your application is going to water your dog instead of walking it. Poor doggy! This code will work perfectly in development, and it will also pass your unit tests without further ado.

That's because production code is minified, while developers prefer to use non-minified code. Webpack (or whichever tool you're using) replaces the word "Dog" with a shorter name. In my case, it simply was "A." So being.constructor.name stopped being Dog, but was A.

Better use instanceof

instanceof works a lot better:

function howToMakeHappy(being: Dog | Oak): string if (being instanceof Dog) { return "walk it"; } else { return "water it"; }

Your dog is happy because it doesn't get wet. Technically speaking: this code also works after minification, because when the class Dog is renamed, this also renames the right-hand side of the instanceof operator.

Even better still: object-orientated approaches

However, as an architect, I don't like this pattern. Please avoid this kind of switch. In real life, dogs know they want to be walked, and they make sure you know it, too. That's the idea of an object-oriented dog. It provides a method howToMakeHappy(). Most oaks are less talkative, but when you try to walk an oak, you'll learn quickly it doesn't like that. So, stretching the analogy a bit, our object-oriented Oak also provides a method howToMakeHappy(). You don't need a third-party class telling them what to like or not.

Can I avoid this class of errors?

Yes, you can. Run your application at least once every day in production mode. If you're using Angular, that's ng s --prod. If that looks like a waste of time to you, keep in mind it took us two developers and three days to find the error I've mentioned above. How much time does it take you? Granted, you've read this article. Chances are you guess the errors within minutes. But similar bugs are lurking out there. How much time does it take you to spot them? In comparison, running ng b --prod is a small price to pay.

What about avoiding production mode?

When I told my co-workers about the minifier and its consequences, they surprised me. They suggested to use the development build in production mode.

That's a bad idea. Minification is here for a reason. Without minification, the memory footprint of your application is much worse, and it's slower, too. The creators of tools like Uglify do a great job guaranteeing that the minified code works exactly like the original sourcecode. Forbidding minification is pretty much the same as banning compilers. No serious developer will do that. You just have to know about the few limitations.

Wrapping it up

Minification is always good for a surprise. It's nasty because every once in a while, a feature works in development mode but fails to work in production code. Plus, it's an exotic error, guaranteeing lengthy debugging sessions. As a rule of thumb, never use the class name as a string.


Comments