JavaScript Primitive Methods
Learn how JavaScript primitives can call methods through temporary object wrappers, with runnable examples and common pitfalls.
Introduction to JavaScript Primitives and Objects
In JavaScript, almost everything you write involves either a primitive or an object. Understanding the difference — and the clever trick that lets primitives behave like objects — is one of the foundations of the language.
A primitive is the simplest, indivisible kind of value. There are seven primitive types: numbers, strings, booleans, undefined, null, symbols, and bigints. An object is a collection of properties and methods.
Here is the puzzle this page solves: a string is a primitive with no methods, yet "hello".toUpperCase() works. How can a value that has no methods call a method? The answer is object wrappers, and this chapter explains exactly how they work.
This page covers what makes primitives special, how JavaScript briefly wraps them so you can call methods, the methods available for each primitive type, and the common mistake of using new with a primitive constructor.
What Makes Primitives Unique
Primitives differ from objects in three important ways.
1. Immutability. Once a primitive value is created, it cannot be changed. A string operation never edits the original string in place — it returns a brand-new string. Trying to assign to a character does nothing (and throws in strict mode):
2. Stored by value. A primitive is held directly in the variable. When you copy it, you copy the value itself, so the two variables are fully independent:
Objects, by contrast, are stored by reference — copying the variable copies only a pointer to the same object.
3. Simple and lightweight. A primitive carries no properties or methods of its own, which makes it fast to create and compare. A boolean like let flag = true; is just a value, with none of the overhead an object would have.
Objects in JavaScript: A Contrast
Objects are the more complex structure. Unlike primitives, they are:
- Mutable — their contents can be changed after creation.
- Reference types — objects are stored and copied by reference, not by value.
- Versatile — they can hold functions, arrays, and other objects.
How Primitives Call Methods: Object Wrappers
So how does "hello".toUpperCase() work if the string has no methods? When you access a property or method on a primitive, JavaScript:
- Creates a temporary wrapper object of the matching type that holds the primitive value.
- Reads the requested method or property from that wrapper.
- Runs it, and returns the result.
- Discards the wrapper object immediately.
The whole dance happens behind the scenes and is heavily optimized by the engine, so it is effectively free. The key takeaway: the primitive itself is never changed and never permanently becomes an object — the wrapper exists only for the duration of that single expression.
The Wrapper Constructors
Five primitive types have a corresponding built-in wrapper constructor that supplies their methods:
- String — for string primitives.
- Number — for numeric values.
- Boolean — for boolean values.
- Symbol — for symbols.
- BigInt — for bigints.
null and undefined have no wrapper, so reading a property on them throws a TypeError (for example null.toString() fails).
String Methods
Strings expose a rich set of methods through the String wrapper. Here a couple of them combine to title-case a sentence:
Note that length is a property, not a method, so it has no parentheses. toUpperCase() returns a new string and leaves greeting untouched, true to the immutability rule above.
Number Methods
Numbers gain methods from the Number wrapper. A frequent one is toFixed(), which rounds to a fixed number of decimals:
Two things to watch for. First, toFixed() returns a string, not a number — typeof (3.14159).toFixed(2) is "string". Second, to call a method directly on a number literal you need extra parentheses or a space: 255..toString(16) also works, but 255.toString(16) is a syntax error because the parser reads the first dot as a decimal point.
Boolean Methods
Booleans can use the Boolean wrapper, most often just toString():
Symbol Methods
Symbols, a unique primitive type, get methods from the Symbol wrapper:
You must call toString() explicitly here — symbols deliberately do not auto-convert to a string in string contexts (like "" + sym), which would otherwise throw a TypeError.
BigInt Methods
BigInt, designed for integers too large for the regular Number type, gets methods from the BigInt wrapper:
The value is passed as a string here because writing it as a numeric literal would exceed the safe integer range and lose precision before BigInt ever sees it.
The Pitfall: Never Use new with Primitive Wrappers
JavaScript lets you build a wrapper object yourself with new Number(1), new String("x"), or new Boolean(false) — but you almost never should. A wrapper created with new is a real object, and every object is truthy, including one that wraps false:
This is a classic source of bugs. Calling the constructor without new is fine and useful — Number("42"), String(123), and Boolean(value) perform plain type conversion and return primitives, not objects.
Summary
- Primitives are simple, immutable values stored by value; objects are mutable and stored by reference.
- Calling a method on a primitive works because JavaScript wraps it in a temporary object, runs the method, then discards the wrapper.
String,Number,Boolean,Symbol, andBigIntsupply the methods;nullandundefinedhave no wrapper and throw if you access a property.- Use wrapper functions without
newfor type conversion. Never usenewto create wrapper objects in everyday code — they are always truthy and behave unexpectedly.
Next, explore the methods of each type in depth in strings, numbers, and bigint.