This book is currently a work in progress. Content is being actively developed.
Chapter 2: Primitive Behaviors
So far, we’ve explored seven built-in primitive value types in JS:null, undefined, boolean, string, number, bigint, and symbol.
Chapter 1 was quite a lot to take in. Once you’re ready to move on, let’s dig into certain behaviors implied by value types for all their respective values.
Primitive Immutability
All primitive values are immutable, meaning nothing in a JS program can reach into the contents of the value and modify it in any way.myAge = 43 statement doesn’t change the value 42. It reassigns a different value 43 to myAge, completely replacing the previous value.
New values are also created through various operations:
Primitives With Properties?
Properties cannot be added to any primitive values:length property:
As mentioned in Chapter 1, these property/method accesses on primitive values are facilitated by an implicit coercive behavior called auto-boxing. We’ll cover this in detail in “Automatic Objects” in Chapter 3.
Primitive Assignments
Any assignment of a primitive value from one variable/container to another is a value-copy:myAge and yourAge variables each have their own copy of the number value 42.
If we later reassign myAge:
String Behaviors
String values have a number of specific behaviors that every JS developer should be aware of.String Character Access
Though strings are not actually arrays, JS allows[ ] array-style access of a character at a numeric (0-based) index:
Character Iteration
Strings are iterables, which means the characters (code-units) can be iterated individually:Symbol.iterator:
Length Computation
The reportedlength value somewhat corresponds to the number of characters in the string, but it’s more complex when Unicode characters are involved.
Basic Length
Basic Length
Most standard characters: one character = one code-point = one code-unit:
Unicode Normalization
Unicode Normalization
Characters like
"é" can be stored as composed or decomposed:Surrogate Pairs
Surrogate Pairs
Extended Unicode characters above code-point 65535 need surrogate pairs:
Grapheme Clusters
Grapheme Clusters
Multiple code-points can cluster into single visual symbols:
Internationalization (i18n) and Localization (l10n)
JS programs can operate in any international language/culture context using the ECMAScript Internationalization API.Right-to-Left (RTL) Languages
Languages like Hebrew and Arabic use RTL ordering:Index-positional access follows logical position, not rendered position.
String Comparison
String values can be compared for both equality and relational ordering.String Equality
The=== and == operators are the most common way to compare strings:
The
=== operator (strict equality) first checks if the types match. If they do, it checks if the values are the same via per-code-unit comparison.The == operator (coercive equality) performs type coercion if the types don’t match. If both operands are already strings, == just hands off to ===.Really Strict Equality
In addition to== and ===, JS provides Object.is():
String Relational Comparisons
The<, <=, >, and >= operators compare strings lexicographically (like dictionary order):
100 is greater than 11. But in lexicographic ordering, the second "0" character (in "100") comes before the second "1" (in "11").
Locale-Aware Relational Comparisons
UselocaleCompare() for locale-specific comparisons:
String Concatenation
Two or more string values can be concatenated using the+ operator:
String Value Methods
String values provide a variety of methods:Character Access
Character Access
charAt(index)- Returns character at indexat(index)- Like charAt, but supports negative indicescharCodeAt(index)- Returns numeric code-unitcodePointAt(index)- Returns whole code-point
Extracting Substrings
Extracting Substrings
substr(start, length)- Extract substring (deprecated)substring(start, end)- Extract substringslice(start, end)- Extract substring (supports negative indices)
Case Conversion
Case Conversion
toUpperCase()- Convert to uppercasetoLowerCase()- Convert to lowercasetoLocaleUpperCase()- Locale-aware uppercasetoLocaleLowerCase()- Locale-aware lowercase
Searching
Searching
indexOf(searchString, position)- Find index of substringlastIndexOf(searchString, position)- Find last indexincludes(searchString, position)- Boolean checksearch(regexp)- Search with regular expressionstartsWith(searchString)- Check if starts withendsWith(searchString)- Check if ends with
Manipulation
Manipulation
concat(...strings)- Concatenate stringsrepeat(count)- Repeat string n timestrim()- Remove whitespace from both endstrimStart()/trimEnd()- Remove whitespace from one endpadStart(length, padString)- Pad start to lengthpadEnd(length, padString)- Pad end to length
Advanced
Advanced
split(separator)- Split into arraymatch(regexp)- Match against regular expressionmatchAll(regexp)- Get all matchesreplace(pattern, replacement)- Replace occurrencesnormalize(form)- Unicode normalizationlocaleCompare(compareString, locales, options)- Locale-aware comparison
Static String Helpers
The following utilities are provided directly on theString object:
String.fromCharCode(...codes)- Create string from code-unitsString.fromCodePoint(...codePoints)- Create string from code-pointsString.raw(template, ...substitutions)- Template tag for raw strings
Number Behaviors
Numbers are used for a variety of tasks, but mostly for mathematical computations.Floating Point Imprecision
One classic gotcha of any IEEE-754 number system — NOT UNIQUELY JS — is that not all operations and values can fit neatly into the IEEE-754 representations:Epsilon Threshold
A common piece of advice uses theNumber.EPSILON value:
Numeric Comparison
Numeric Equality
Just like strings, equality comparisons for numbers use== / === or Object.is():
== prefers numeric comparison:
Numeric Relational Comparisons
The relational operators work with numbers as expected:==, the < and > operators are also coercive. Ensure both operands are numbers to avoid coercion.
Mathematical Operators
The basic arithmetic operators are+, -, *, /, ** (exponentiation), and % (modulo):
The
+ operator is overloaded: when one or both operands is a string, it performs string concatenation. Otherwise, it performs numeric addition.+ and - operators:
Increment and Decrement
The++ and -- operators perform their operation and reassign:
Bitwise Operators
JS provides several bitwise operators that work on 32-bit signed integers:&(AND),|(OR),^(XOR),~(NOT)<<(left shift),>>(sign-propagating right shift)>>>(zero-fill right shift)
Number Value Methods
Number values provide these methods:toExponential(fractionDigits)- Scientific notation stringtoFixed(digits)- Fixed decimal placestoPrecision(precision)- Significant digitstoLocaleString(locales, options)- Locale-aware string
The
. can be ambiguous with number literals. Use whitespace or parentheses:Static Number Properties
Number.EPSILON- Smallest difference between 1 and next valueNumber.MIN_SAFE_INTEGER/Number.MAX_SAFE_INTEGER- Safe integer rangeNumber.MIN_VALUE/Number.MAX_VALUE- Representable value rangeNumber.NEGATIVE_INFINITY/Number.POSITIVE_INFINITY- Infinite valuesNumber.NaN- The special invalid number value
Static Number Helpers
Number.isFinite(value)- Check if finiteNumber.isInteger(value)- Check if integerNumber.isSafeInteger(value)- Check if safe integerNumber.isNaN(value)- Check if NaN (bug-fixed version)Number.parseFloat(string)- Parse floatNumber.parseInt(string, radix)- Parse integer
Static Math Namespace
JS includes many mathematical constants and utilities on theMath namespace:
BigInts and Numbers Don’t Mix
Values ofnumber type and bigint type cannot mix in operations:
Primitives Are Foundational
Over the last two chapters, we’ve dug deep into how primitive values behave in JS. The story doesn’t end here — in the next chapter, we’ll turn our attention to understanding JS’s object types.Continue to Chapter 3
Learn about object values, arrays, functions, and how they differ from primitives

