SKU // 102

JavaScript toString()

toString() turns a value into a string. Almost every value has one, and JavaScript quietly calls it for you whenever a value has to become text: when you join it to a string, put it in a template literal, or show it on a page. Knowing what each type produces explains a lot of strange-looking output.

// Numbers

On a number, toString() returns the digits as text. Give it a radix (base) from 2 to 36 to write the number in another base:

const x = 123;

console.log(x.toString());       // base 10
console.log(x.toString(2));      // binary
console.log((255).toString(16)); // hexadecimal
console.log((-10).toString(2));
123 1111011 ff -1010

To go back, parseInt takes the same base: parseInt("1111011", 2) is 123. A base outside 2 to 36 is an error: (10).toString(1) is RangeError: toString() radix argument must be between 2 and 36.

Watch out: toString on a number literal
123.toString() is SyntaxError: Invalid or unexpected token. JavaScript reads 123. as the start of a decimal number. Wrap the number in parentheses, (123).toString(), or use a variable.

// Arrays

An array becomes its items separated by commas, with no spaces. Nested arrays are flattened, and null and undefined become empty:

const fruits = ["Banana", "Orange", "Apple", "Mango"];

console.log(fruits.toString());
console.log([1, [2, 3]].toString());
console.log([null, undefined, 1].toString());
console.log(fruits.join(" | "));      // join lets you pick the separator
Banana,Orange,Apple,Mango 1,2,3 ,,1 Banana | Orange | Apple | Mango

// Dates

A date becomes a long, human-readable string:

const d = new Date(2026, 0, 5, 14, 30);

console.log(d.toString().slice(0, 24));
console.log(d.toDateString());
Mon Jan 05 2026 14:30:00 Mon Jan 05 2026

The full d.toString() continues with your time zone, like GMT-0500 (Eastern Standard Time), so it differs from computer to computer. For display, toLocaleString() (next lesson) gives you much more control.

// Booleans and Functions

function add(a, b) { return a + b; }

console.log(true.toString(), false.toString());
console.log(add.toString());
console.log(((x) => x * 2).toString());
console.log(Math.max.toString());
true false function add(a, b) { return a + b; } (x) => x * 2 function max() { [native code] }

A function gives back its own source code. Built-in functions are written inside the browser, not in JavaScript, so they only show [native code].

// Objects: [object Object]

A plain object has a toString(), but it is not useful (you met this in Object Display):

const person = { firstname: "John", lastname: "Doe" };

console.log(person.toString());
console.log("Hello " + person);
[object Object] Hello [object Object]

// Writing Your Own toString()

Give an object its own toString method, and JavaScript uses it every time the object has to become text:

const person = {
  firstname: "John",
  lastname: "Doe",
  toString() {
    return this.firstname + " " + this.lastname;
  }
};

console.log(person.toString());
console.log("Hello " + person);
console.log(`Welcome, ${person}!`);
John Doe Hello John Doe Welcome, John Doe!

It works the same in a class, and then every object made from the class prints nicely:

class Temp {
  constructor(c) { this.c = c; }
  toString() { return this.c + "°C"; }
}

const readings = [new Temp(21), new Temp(5)];
console.log(`Now: ${readings[0]}`);
console.log(readings.join(", "));
Now: 21°C 21°C, 5°C
W3Schools error
W3Schools says an object's toString() "can be overridden in the object definition," but its example never overrides it: the person it shows has no toString method, so the result is just [object Object]. The example above is what overriding looks like.

// null and undefined Have No toString()

They are the two values with no properties at all, so calling a method on them crashes. String() handles every value safely:

console.log(String(null), String(undefined));
console.log(null.toString());
null undefined TypeError: Cannot read properties of null (reading 'toString')
Way Handles Use when
x.toString()Throws for null and undefinedYou know x is a real value, or you need a radix
String(x)Works for every valueSafe general conversion
`${x}` or "" + xWorks except for SymbolsBuilding a larger string
Rule of Thumb
Reach for String(x) when you just need text. Use toString() when you want its extra power: a radix for numbers, or your own custom method on an object.

// Quick Check

What does this log?

console.log([1, [2, [3]], null].toString());
Show answer
1,2,3,. Nested arrays are flattened into the list, and null becomes an empty item, which leaves a trailing comma.

Which one throws a TypeError?

  1. String(null)
  2. `${null}`
  3. null.toString()
  4. null + ""
Show answer
C. null has no methods. The other three all produce the text "null".

(255).toString(16) gives "ff". How do you turn "ff" back into 255?

Show answer
parseInt("ff", 16). The second argument tells parseInt the text is in base 16.

// Try It

  1. Click Open Playground and run it: the numbers 0 to 16 in binary. Change the 2 to 16 for hexadecimal
  2. Log [1, [2, 3], [], null].toString() and explain each comma
  3. Give an object a toString method and use it inside a template literal
  4. Write safeText(x) that never crashes, even for null and undefined
// Video Walkthroughs
Last updated: Oct 10, 2026, 1:48 AM ET