Fundamentals 11 min read

JavaScript Implicit Type Conversions You Didn't Know

This article examines JavaScript’s implicit type conversion mechanisms, illustrating a quirky yet functional code example, detailing conversion rules for symbols, objects, arrays, numbers, booleans, and undefined/null, and highlighting common pitfalls and practical coding tricks.

大转转FE
大转转FE
大转转FE
JavaScript Implicit Type Conversions You Didn't Know

JavaScript is a dynamic, weakly typed language that performs many implicit type conversions. This article starts with a seemingly crazy but valid code snippet and then explains the rules behind JavaScript’s implicit coercion.

Crazy but Valid Code

The following expression works because of JavaScript’s type conversion rules:

// a
(![]+[])[+!![]] === "a"

Conversion Rules

Symbol

Operation Rule

[]

Empty array, treated as truthy.

!

Logical NOT, converts operand to boolean and negates it.

!!

Double NOT, forces a value to boolean.

+

When one operand is a string (or can be converted to a string), the other operand is also converted to a string and concatenated.

Conversion Steps

Symbol

Computation Process

Result

![]

Empty array

[]

is truthy; applying

!

yields

false

.

(false+[])[+!![]]

![] + []

false

concatenated with

[]

becomes the string "false".

("false")[+!![]]

!![]

Double NOT converts to

true

.

("false")[+true]

+!![]

Converts

true

to the number

1

.

("false")[1]

(![]+[])[+!![]]

Indexes the string "false" at position 1, yielding the character

"a"

.

"a"

Further Exploration

Using only the characters ! , ( , ) , [ , ] , and + , developers can construct many obscure expressions. The site JSFuck demonstrates this with thousands of characters to produce simple strings.

Type Conversion Rules

Basic Implicit Conversions

Arithmetic Operators

When the + operator involves a string, the other operand is converted to a string; otherwise, operands are converted to numbers.

// + with a string converts both to strings
console.log(1 + '1')    // '11'
// other cases
console.log(1 + true)   // 2 : number + boolean
console.log(true + false) // 1 : boolean + boolean
console.log(1 - false)  // 1 : number - boolean
console.log(true - false) // 1 : boolean - boolean
console.log(-1 * '1')    // -1 : number * string
console.log(-1 / true)   // -1 : number / boolean
console.log(2 ** ('1' + 0)) // 1024 : number ** (string + number)
console.log(100 % ('1' + 0)) // 0 : number % (string + number)

Logical Operators

The NOT operator ( ! ) converts its operand to boolean. The OR ( || ) and AND ( && ) operators perform short‑circuit truthy/falsy evaluation.

// NOT
console.log(!true)   // false
console.log(![])     // false
console.log(!!{})    // true
// OR and AND
console.log(0 || 1)   // 1
console.log(1 || 0)   // 1
console.log(0 && 1)   // 0
console.log(1 && 0)   // 0

Bitwise Operators

Bitwise operators ( & , | , ^ , ~ , << , >> ) first convert operands to 32‑bit integers.

console.log(2 & 3)   // 2 (010 & 011 = 010)
console.log(2 | 3)   // 3 (010 | 011 = 011)
console.log(2 ^ 3)   // 1 (010 ^ 011 = 001)
console.log(~2)      // -3 (bitwise NOT)
console.log(2 << 1)  // 4 (010 << 1 = 100)
console.log(4 >> 1)  // 2 (100 >> 1 = 010)

Complex Implicit Conversions

Object to Primitive

When an object participates in an operation, JavaScript calls its valueOf() and/or toString() methods to obtain a primitive.

let obj = {
  toString() { return '42'; },
  valueOf() { return 10; }
};
console.log(obj + 10); // 52 (valueOf() returns 10, then string concatenation)
console.log(String(obj)); // '42'

Symbol Type

Symbols cannot be implicitly converted to strings or numbers; attempting to do so throws a TypeError .

let sym = Symbol('example');
try { console.log('symbol: ' + sym); } catch(e) { console.log(e); }
try { console.log(sym + 10); } catch(e) { console.log(e); }
console.log(String(sym)); // 'Symbol(example)'

Common Implicit Conversion Pitfalls

Array and Number Operations

console.log([] + 1);      // '1'
console.log([1] + 1);    // '11'
console.log([1,2] + 1);  // '1,21'

Empty array becomes an empty string, a single‑element array becomes the element’s string, and a multi‑element array joins its elements with commas before concatenation.

Empty Object and Boolean Comparison

console.log({} == true);   // false
console.log({} == false);  // false
console.log([] == true);   // false
console.log([] == false);  // true

When compared to a boolean, both sides are converted to numbers; {} becomes NaN , while [] becomes 0 .

undefined and null

console.log(undefined + 1); // NaN
console.log(null + 1);      // 1
console.log(undefined == null); // true

undefined cannot be converted to a number, yielding NaN . null is treated as 0 in arithmetic, and both values are considered equal with == .

Implicit Conversions in Real‑World Scenarios

JSON and Object Conversion

let jsonStr = '{"a": 1, "b": "2"}';
let obj = JSON.parse(jsonStr);
console.log(obj.a + obj.b); // '12' (number + string => string concatenation)

Type Conversion in Conditional Statements

let x = 0;
let y = '0';
if (x == y) { console.log('x == y'); }   // prints
if (x === y) { console.log('x === y'); } // does not print
if (x || y) { console.log('x || y'); }   // prints '0'

Loose equality ( == ) coerces y to a number, making the comparison true; strict equality ( === ) does not. The logical OR returns the first truthy operand.

Conclusion

The article demonstrates the power and complexity of JavaScript’s implicit type conversion, showing how seemingly bizarre code can be valid and how understanding these rules is essential for writing robust JavaScript.

JavaScriptcoding tricksoperatorsJSFucktype coercionimplicit conversion
大转转FE
Written by

大转转FE

Regularly sharing the team's thoughts and insights on frontend development

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.