Rebuilding JavaScript String Methods from Scratch
I will never forget the sudden, cold sweat of my first real whiteboard interview.
I had been studying for weeks. I knew React. I knew how to fetch data. I felt invincible. The interviewer, a quiet senior developer, walked up to the whiteboard, handed me a dry-erase marker, and said:
"Write a function that takes a string and reverses it."
I smiled. This was a joke, right? I immediately wrote:
function reverseString(str) {
return str.split('').reverse().join('');
}
I put the cap back on the marker, feeling like a genius. The interviewer looked at it, nodded slowly, and then dropped the hammer.
"Great. Now do it without using .split(), .reverse(), or .join(). Act like those methods don't exist."
My mind went completely blank. I had spent so much time learning how to use JavaScript's tools that I had absolutely no idea how they actually worked inside the box. I viewed the language as magic.
That day, I learned a very hard lesson: if you want to be a truly great developer—and if you want to survive technical interviews—you have to stop relying on magic. You need to know how to build the tools yourself.
Today, we are going deep. We are going to look at what string methods actually are, why developers write something called "polyfills," and we are going to rebuild some of JavaScript’s most famous string methods entirely from scratch.
What exactly is a String Method?
Before we rebuild the engine, we have to open the hood.
In JavaScript, a string is technically a "primitive" value. It’s just raw text. const name = "Alice";.
But wait a minute. If it's just raw text, how can we do things like name.toUpperCase()? How can raw text have functions attached to it with a dot? Objects have methods. Text shouldn't.
JavaScript does something incredibly sneaky here called auto-boxing.
When you try to use a method on a string, JavaScript quickly, invisibly wraps your raw text inside a temporary String object, runs the method you asked for, gives you the result, and then instantly destroys the temporary object. It happens so fast you never notice it.
All of those built-in tools—.toLowerCase(), .substring(), .indexOf()—live inside a master blueprint called String.prototype.
But what happens when the tool you need isn't in the blueprint? Or what happens if you're stuck in an interview and they lock the toolbox?
Enter the Polyfill
The word "polyfill" sounds like a chemical you use to insulate a house. And honestly, the metaphor isn't that far off.
A polyfill is a piece of code (usually a function) that provides technology that you expect the browser to have natively, but it currently doesn't.
Back in the dark ages of web development (the Internet Explorer era), browsers updated very slowly. If JavaScript released a cool new string method, you couldn't use it for years, because half your users' browsers wouldn't know what it meant.
So, developers wrote polyfills. They literally wrote their own versions of the new methods using old, basic JavaScript, and "plugged the hole" in the older browsers. It was like using spackle to fill a crack in a wall.
Today, we don't have to worry about old browsers as much. But writing polyfills is still the absolute best way to prepare for a technical interview. It forces you to break down complex actions into tiny, logical steps.
Let’s roll up our sleeves and write a few.
Implementation 1: Rebuilding .repeat()
The .repeat() method is wonderfully simple. You give it a number, and it returns a new string containing your text repeated that many times.
"ha".repeat(3) gives you "hahaha".
The Interview Constraints: Write a function myRepeat(str, count) that does this. Do not use the built-in .repeat() method.
The Thought Process: We need to start with an empty canvas (an empty string). Then, we need to loop count number of times. Inside that loop, we just keep gluing the original string onto our canvas.
function myRepeat(str, count) {
// Edge Case 1: What if they ask for negative repeats? That's impossible.
if (count < 0) {
throw new RangeError("Repeat count must be positive");
}
let result = ""; // Our empty canvas
for (let i = 0; i < count; i++) {
result += str; // Glue the string on
}
return result;
}
console.log(myRepeat("ha", 3)); // Output: "hahaha"
In an interview, the code is only half the battle. The fact that we paused to think, "Wait, what if they pass a negative number?" shows the interviewer that you are thinking like an engineer, not just a typist.
Implementation 2: Rebuilding .startsWith()
Let's turn up the heat slightly. The .startsWith() method checks if a string begins with a specific word or letter. It returns true or false.
"hello world".startsWith("hell") returns true.
The Interview Constraints: Write myStartsWith(str, searchString). No using .startsWith(), .indexOf(), or .includes().
The Thought Process: How do humans solve this? If I hand you the word "hello" and ask if it starts with "he", your eyes look at the first letter of both words. 'h' matches 'h'. Then you move to the second letter. 'e' matches 'e'. You reached the end of your search string, and everything matched, so it's true.
We need to make JavaScript do exactly that. We loop through the searchString character by character, and compare it to the exact same position in the main str.
function myStartsWith(str, searchStr) {
// Edge Case: If the search string is longer than the main string,
// it's literally impossible for it to start with it.
if (searchStr.length > str.length) {
return false;
}
// Loop only for the length of what we are searching for
for (let i = 0; i < searchStr.length; i++) {
// If we find a single mismatch, stop immediately and return false!
if (str[i] !== searchStr[i]) {
return false;
}
}
// If we made it all the way through the loop without returning false,
// everything must have matched!
return true;
}
console.log(myStartsWith("javascript", "java")); // true
console.log(myStartsWith("javascript", "script")); // false
Look at that if (str[i] !== searchStr[i]) logic. That right there is the core of algorithmic thinking. We don't try to prove it's true. We try to find a reason to prove it's false. The millisecond we find a mismatch, we bail out and return false to save computing power.
Implementation 3: Rebuilding .trim() (The Two-Pointer Technique)
Okay, let's step into the uncomfortable zone. This is a heavy-hitter interview question.
The .trim() method removes empty spaces from the beginning and the end of a string, but not the middle.
" hello world ".trim() returns "hello world".
The Interview Constraints: Write myTrim(str). You cannot use .trim(), and you cannot use Regular Expressions (Regex). You have to do it manually.
The Thought Process: This is where we use a famous interview concept called the Two-Pointer Technique.
Imagine you have two fingers. You put your left finger at the very beginning of the string, and your right finger at the very end.
Your left finger steps forward one character at a time until it stops touching an empty space. Your right finger steps backwards one character at a time until it stops touching an empty space.
Once both fingers have stopped, you just cut out the text that is trapped between them.
Here is how we translate that finger movement into code:
function myTrim(str) {
let start = 0; // Left finger
let end = str.length - 1; // Right finger
// Move the left finger forward as long as it touches a space
// We also check start <= end to make sure the fingers don't cross each other!
while (start <= end && str[start] === " ") {
start++;
}
// Move the right finger backward as long as it touches a space
while (end >= start && str[end] === " ") {
end--;
}
// Now, extract the string between the two fingers
// Note: substring doesn't include the 'end' index itself, so we add 1
return str.substring(start, end + 1);
}
console.log(myTrim(" hello world ")); // "hello world"
Why doing this makes you a better developer
If you are just building websites to get by, you don't need to know how to write a polyfill. The built-in methods are highly optimized and written in underlying C++ in the browser. You should use them in your day job.
But if you want to level up, understanding the underlying logic is non-negotiable.
When you know that .trim() requires looping through the start and end of a string, or that .includes() requires checking characters one by one, you stop viewing JavaScript as a black box. You start understanding the cost of the code you write. You realize that calling .trim(), .split(), .reverse(), and .join() all in one giant chain is actually looping over your data four separate times under the hood.
The next time an interviewer asks you to build something from scratch, don't panic. Take a breath. Look at the problem the way a human would solve it with their eyes and hands, and then translate that into simple loops and logic.
You are the one writing the magic now.





