JavaScript quirks: tips and tricks to using JS

As a language that is widely accessible, but deceptively hard to master, JavaScript has many subtleties which can cause even experienced programmers to stumble. This VOX DC post provides a few helpful tips for the engineer new to JavaScript.

Equality (==) versus Identity (===)

This seems to be the first construct noticed by experienced engineers new to the language. To fully understand why JavaScript has both operators, one must recognize JavaScript is a dynamically-typed language; an identifier1 has no type permanently bound to it. For instance, the value of a programmatically defined variable may be a number, string, and object at one point during the same lifecycle.

With this in mind, the equality operator (==) ignores the type of the identifier and only compares the value. In such case the expression 1 == ‘1’ would evaluate to true as we are only comparing the value—which is the digit “1”—and not the type—number versus string. How the JavaScript interpreter does this is through what is called “type coercion,” wherein the types are attempted to be modified to match each other before subsequently comparing the values.

If we would like to include type in our comparison, we must use the identity operator (===). Now, using the same arguments as the previous example, the expression 1 === ‘1’ would result in false.

In the case of non-primitives (i.e. objects), the reference is always used for comparison, thereby eradicating the operator discrepancy.

It is best practice to use the identity operator (commonly referred to as “strict equality”) in all cases to avoid unforeseen behavior and potential errors caused by having the incorrect type. Any linter should be configured as such.

  1. An identifier is a parameter, variable, or object key.

Null (null) versus Undefined (undefined)

While these pieces of the language often behave similarly, they are not equivalent. The keyword undefined is used internally by the JavaScript interpreter to denote the value of any identifier that has not been initialized or one that has been destroyed, either by the programmer (e.g. with the delete keyword) or through garbage collection. It is its own type. In contrast, the keyword null is present exclusively for use by the programmer. The JavaScript interpreter will never reference null unless it is first used by the programmer; that is, an identifier can only be set to null programmatically. It is of type ‘object’.

Considering this, it is best practice to avoid explicitly setting an identifier to undefined as it can lead to ambiguity as to whether the value was previously set. Both null and undefined evaluate to false in a Boolean context.

Truthy and Falsy values

No, that is not a typo – JavaScript has 'truthy’ and ‘falsy’ values, which as the names suggest, are entities that evaluate to true and false, respectively, in the context of a logical expression.

Truthy values are best described as anything that is not falsy. Falsy values are precisely false, 0, ‘’ (empty string), NaN (not a number), undefined, and null. Notice how they correlate to fundamental types of the language – number, string, Boolean, and object. These values may be used directly in conditional expressions (e.g. ternary operator or if-statement) without the need for further operators due to type conversion highlighted earlier.

JavaScript object literals versus JSON

While JSON is based on JavaScript object syntax, it is important to recognize the fundamental differences between the two. JSON is language agnostic data interchange format like XML or YAML which rightfully has strict formatting specifications. These include no trailing commas, no comments, mandatory use of double quotes (“”) to wrap all key values, and values of type null, Boolean, string, array, or nested JSON. In contrast JavaScript object literals are the most common of several ways to define an object in JavaScript and should not be thought of as JSON (despite the name), since they do not hold any of same restrictions detailed above.

The is worthy of mention because engineers who have worked with JSON come to JavaScript and expectedly feel the need to write JavaScript literals as if they are JSON. The built-in global JSON object properly handles serialization and deserialization of JSON in JavaScript.

Altogether, these are a few notable things unique to JavaScript. As a developer who has been programming in JavaScript as long as I have been programming, I hope you find something to appreciate within the language. And please join me in the VOX Developers' Community for more coding and language best practices from Veritas engineers.