Weird JavaScript Part 1—10 Strange JavaScript Facts You’ve Never Known Before



Trust me — even senior devs haven’t

So, JavaScript is among the most popular programming languages today and is used for websites, mobile apps, and even servers. But, behind its potent capabilities is a plethora of abnormal, occasionally mind-boggling behavior that may astound even the most experienced developers. In this article, we explore ten of these bizarre facts about JavaScript — with code examples — and explain how and why these oddities happen and how they can impact your code.

1. NaN Is Not Equal to NaN

One of the just-weird things about JavaScript is that the “Not-a-Number” value, NaN, does not equal itself.

console. log(NaN === NaN); // false

Explanation:

Floating-point numbers in JavaScript use the IEEE 754 standard. NaN is a special value indicating an undefined or unrepresentable number, so any comparison (even to itself) will always return false. You can check for NaN using the isNaN() or the more robust Number.isNaN() method.

console. log(Number. isNaN(NaN)); // true

2. The “Banana Trick”: Weirdness from String Coercion

Have you ever come across the below code?

console. log("b" + "a" + + "a" + "a"); // "baNaNa"

Explanation:

Here’s the breakdown:

“b” and “a” are strings.

For the statement + “a,” towards the end of the line, the + gets the first input as a data type number and the “a” as a string; thus, node converts the string “a” into a number. The value a cannot be cast to a valid number, and as such, it is NaN.

Then JavaScript does string concatenation, which turns NaN into the string “NaN.”

So, the final result is: “b” + “a” + “NaN” + “a” => “baNaNa.”

This clever twist on type coercion is one of JavaScript’s best-known oddities.

3. Automatic Semicolon Insertion (ASI) Gotcha

Note that JavaScript can add semicolons for you. But this “helpful” feature can backfire in return statements.

Consider this function:

function getObject() {
return
{
greeting: "Hello"
};
}
console. log(getObject()); // undefined!

Explanation:

Due to ASI, a semicolon is added for us after return, making the function return undefined instead of the object. To resolve this, place the object literal on the same line with return or wrap in parentheses:

function getObjectFixed() {
return {
greeting: "Hello"
};
}
console. log(getObjectFixed()); // { greeting: "Hello" }

4. Call Before Declaration: Function Hoisting

‘Hoisting’ is when function declarations are ascended to the highest point of their scope in JavaScript. This means you can invoke a function before it seems to be defined in the code.

sayHello(); // "Hello, world!
function sayHello() {
console. log("Hello, world!" );
}

Explanation:

JavaScript hoists function declarations to the top of their scope during compilation. This hoisting lets functions be called before the actual line where they are declared appears in the source code.

5. typeof null Returns “object.”

One of the oddities of JavaScript is that null, which means “no value,” returns an object when checked with typeof.

console. log(typeof null); // "object"

Explanation:

This behavior is a long-standing bug from the very first version of JavaScript. In its original design, a type tag indicated value (null, represented as a null pointer (value 0) that was incorrectly considered an object). While this bug has been kept for backward compatibility, it is still one of JavaScript’s most justly famous oddities.

6. This May Be A Trap: Loose Equality (==)

JavaScript’s loose equality operator == coerces types and gives us, sometimes, surprising results.

console. log(0 == "0"); // true
console. log(false === []); // false
console. log("" == false); // true

Explanation:

When comparing values of different types, == first converts them to a type they have in common, then performs the comparison. Such coercion can lead to surprising results. To avoid such mistakes, always use the strict equality operator (===), which performs no type coercion.

console. log(0 === "0"); // false

7. The this Keyword — Context Is Everything

In JavaScript, the context of this can change drastically depending on the way their function has been called.

const obj = {
showThis: function() {
console.log(this);
}
};
obj. showThis(); // Logs the 'obj' itself
const detachedFunction = obj. showThis;
detachedFunction(); // Logs the global object (window) in non-strict mode, undefined in strict mode

Explanation:

When a function is invoked as an object method, this is the object. But when this function is assigned to a variable and called as a standalone function, it loses its original context. 1. Identifying and binding the correct context (with a.bind(), .call(), or .apply()) which is why its use (together with apply()) is crucial in terms of preventing unexpected behaviors.

8. You may notice that we did not declare our variable using var, let, or const.

If you forget to use var, let, or const when declaring a variable, JavaScript will create a global variable, which is a terrible idea inside a function.

function setValue() {
myValue = 10; // No declaration keyword!
}
setValue();
console. log(myValue); // 10 (global!)

Explanation:

This can cause unintended side effects and introduce bugs because it pollutes the global namespace. Use let or const (or var, for legacy code) to announce variables and keep your scope clear.

9. Arrow Functions Don’t Bind Their Own this

Arrow Functions Arrow functions, introduced in ES6, are a feature of JavaScript that allows for a more concise syntax compared to the traditional function expressions. However, they vary quite a bit in the way they accomplish this.

const objArrow = {
value: 42,
getValue: () => {
console.log(this.value);
}
};
objArrow. getValue(); // usually logs 'undefined'

Explanation:

Arrow functions also do not bind their own this. They use the one from the surrounding (lexical) scope instead. In our above example, if the surrounding context was global scope, then this would mean a global object (or undefined in strict mode). Use regular functions for methods that rely on their own this binding.

10. Adding Arrays and Objects Gives Mysterious Output

If the operand type is a string, the + operator performs concatenation. For instance:

console. log([] + []); // ""
console. log([] + {}); // "[object Object]"
console. log({} + []); // 0 - (and weird!)

Explanation:

Both empty arrays are casted to empty strings and concatenated in the first example.

For [] + {}, the empty array is converted to the empty string, and the empty object to “[object Object].”

In the case of {} + [], the leading {} is interpreted as an empty code block instead of an object literal, followed by the unary plus operator that converts the empty array ([]) to a number (which is 0). If you want to force the object literal, wrap it in parentheses:

console. log({} + []); // Could give 0
console. log(({} + [])); // "[object Object]"

This small difference illuminates how different results in JavaScript stem from type coercion based on context (; vs,)!

Conclusion

Javascript is one of the surprising languages. Its strange behaviors, from how it treats NaN and null to the weirdness of how this and type coercion work, can be downright confusing in the beginning. But knowing these quirks lets you leverage the language with more power and write intrinsically more stable, bug-resistant code. What JavaScript quirk has surprised you the most? Let us know if you think so or not, of course, in the comments!



Weird JavaScript Part 1—10 Strange JavaScript Facts You’ve Never Known Before Weird JavaScript Part 1—10 Strange JavaScript Facts You’ve Never Known Before Reviewed by Mady on April 15, 2025 Rating: 5

No comments:

Powered by Blogger.