How to count a string's length without built-in methods or properties (length)?
Short answer
You can count a string's length with a simple pass over the characters and a counter increment, without using length or string methods. Below are two basic variants: via for..of (counting Unicode code points) and via indexing (counting UTF-16 code units).
// Variant A: by code points (accounts for surrogate pairs)
function strLengthByIteration(str) {
let count = 0;
for (const _ of str) count++;
return count;
}
// Variant B: by code units (like String#length)
function strLengthByIndexing(str) {
let i = 0;
while (true) {
if (str[i] === undefined) return i;
i++;
}
}Detailed explanation
What exactly counts as "length"
- Code units (UTF-16): matches the behavior of String.length and the index str[i]. Emoji outside the BMP take 2 code units.
- Code points (Unicode code points): for..of correctly merges surrogate pairs, counting such characters as one.
- Grapheme clusters (what a user sees as a single character): can consist of several code points (for example, ZWJ sequences and combining diacritics). Accurate counting needs a grapheme segmentation algorithm.
Solutions
- Counting code points without methods and length (preferred in an interview):
function codePointLength(str) {
let n = 0;
for (const _ of str) n++;
return n;
}- Counting code units without methods and length (a strict repeat of String.length's logic):
function codeUnitLength(str) {
let i = 0;
while (true) {
if (str[i] === undefined) return i;
i++;
}
}- If you need the length in grapheme clusters: without external libraries, the simplest option is the standard segmentation API (if using it is allowed):
function graphemeLength(str) {
if (typeof Intl !== 'undefined' && Intl.Segmenter) {
const seg = new Intl.Segmenter('en', { granularity: 'grapheme' });
let count = 0;
for (const _ of seg.segment(str)) count++;
return count;
}
// Fallback: count code points
let n = 0;
for (const _ of str) n++;
return n;
}Verification and examples
const samples = [
"Hello",
"café",
"\u{1F600}", // one code point, two code units
"\u{1F468}\u{1F469}\u{1F467}\u{1F466}", // a family: several code points, one visible character
"é", // e + a combining accent, two code points, one visible character
"\u0000abc" // contains a null character
];
for (const s of samples) {
console.log('s =', JSON.stringify(s));
console.log('codePointLength:', codePointLength(s));
console.log('codeUnitLength :', codeUnitLength(s));
console.log('graphemeLength :', graphemeLength(s));
console.log('---');
}Edge cases and nuances
- Empty string: both basic algorithms return 0.
- A null character inside the string: indexing is safe, because the check is strictly against undefined, not against truthy/falsy.
- Emoji and characters outside the BMP: for..of accounts for surrogate pairs and gives a correct code point count.
- Combining diacritics and ZWJ sequences: one visible character can consist of several code points; use grapheme segmentation for this.
- Performance: all variants run in O(n) time and O(1) memory.
Complexity
Time is O(n), memory is O(1), where n is the length of the input string in the chosen unit (code units/code points/graphemes).
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.