Capitalize the First Letter
Capitalising the first letter of a string is a tiny task that hides several gotchas: empty inputs, multi-word phrases, and Unicode characters whose uppercase form is more than one code unit. This snippet starts with the obvious one-liner, hardens it against `null`/`undefined`/empty strings, then upgrades to a code-point-safe variant and finally a per-word title-case helper. Drop these in for form labels, headings, and CSV column titles.
455 views
12
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
console.log(capitalize('hello')); // Hello
console.log(capitalize('world')); // World
console.log(capitalize('')); // (empty string, no error)The classic two-step uppercases the first character with charAt(0).toUpperCase() and concatenates slice(1) for the rest. Using charAt(0) over str[0] matters for the empty-string case because charAt returns '' whereas str[0] returns undefined, which would stringify to 'undefined' and break the output. This implementation runs in O(n) because slice copies the tail, but the constant factor is tiny and good enough for typical UI strings. Reach for it when you control the input and just need to fix one form label.
function capitalize(input) {
if (typeof input !== 'string' || input.length === 0) return '';
return input[0].toUpperCase() + input.slice(1);
}
console.log(capitalize('javaScript')); // JavaScript
console.log(capitalize('')); // (empty)
console.log(capitalize(null)); // (empty)
console.log(capitalize(undefined)); // (empty)
console.log(capitalize(42)); // (empty, type-guarded)In a real codebase, the input often arrives from a form, an API response, or a JSON column where it can be null, undefined, or even a number. A tiny typeof plus length check turns those silent corruptions into a predictable empty string. Note that this version intentionally does not lowercase the rest of the input, so 'iPhone' stays 'IPhone'-style without mangling already-cased acronyms. Use this whenever the value comes from an unknown source you cannot fully trust.
function capitalizeUnicode(str) {
if (typeof str !== 'string' || str.length === 0) return '';
const first = String.fromCodePoint(str.codePointAt(0));
return first.toUpperCase() + str.slice(first.length);
}
// German sharp S: 'ß'.toUpperCase() === 'SS' (one char becomes two)
console.log(capitalizeUnicode('ßeta')); // SSeta
// Surrogate-pair character (mathematical italic 'a'): U+1D44E
console.log(capitalizeUnicode('\u{1D44E}bc')); // 𝑎bc (no upper form, unchanged head)
// Combining marks stay attached to the right base char
console.log(capitalizeUnicode('école')); // Écolestr[0] and charAt(0) operate on UTF-16 code units, which silently splits surrogate pairs (any character outside the Basic Multilingual Plane) into two halves. Using codePointAt(0) plus String.fromCodePoint keeps the first user-perceived character intact, then slice(first.length) advances past either one or two code units depending on whether the head was a BMP character or a surrogate pair. The German ß example also shows that toUpperCase() can grow the string (one code point becomes 'SS'), so do not assume the output length matches the input. Pick this variant whenever your strings can contain non-ASCII content like accented Latin, Cyrillic, math italics, or emoji-adjacent symbols.
function titleCase(str) {
if (typeof str !== 'string') return '';
return str
.toLowerCase()
.split(/\s+/)
.filter(Boolean)
.map((w) => w[0].toUpperCase() + w.slice(1))
.join(' ');
}
console.log(titleCase('hello world')); // Hello World
console.log(titleCase(' the quick BROWN fox')); // The Quick Brown Fox
console.log(titleCase('')); // (empty)Title case is the natural extension: split on whitespace, capitalize each word, and join back with single spaces. The .toLowerCase() first pass normalises shouting input like 'BROWN' so it does not stay 'BROWN' after the per-word capitalize, and .filter(Boolean) removes the empty entries produced by runs of whitespace. This is deliberately ASCII-naive: locale-specific small words (English 'and', French 'de') are still capitalized, which is fine for most UI use but wrong for editorial style. For headlines or CMS titles, layer a stop-word list on top, but for table headers and labels this version is enough.
