Hello readers 👋, welcome to the 24th blog in this JavaScript series!
Last time we explored the clever spread and rest operators, learning how the same three dots can either unpack or collect data. Today we are shifting gears to a topic that deeply sharpens your understanding of how JavaScript works under the hood: string polyfills and common interview methods.
Have you ever wondered how "hello".includes("ell") works inside the engine? Or how you could make the same behavior work in an old browser that doesn't support includes? That's exactly what we are going to dive into. We will not just use string methods, we will build several of them from scratch, understand the logic, and then solve some classic interview string problems.
Let's get our hands dirty.
What string methods are
In JavaScript, every string is a primitive value, but when you access a property or method on it, the engine wraps it in a String object behind the scenes. This gives you access to a large set of built-in methods like indexOf, slice, substring, includes, startsWith, endsWith, trim, repeat, and many more.
These methods help you manipulate and inspect strings without manually looping through characters. For example:
const greeting = "Hello, Satya";
console.log(greeting.includes("Satya")); // true
console.log(greeting.startsWith("Hello")); // true
console.log(greeting.endsWith("ya")); // true
console.log(greeting.repeat(2)); // "Hello, SatyaHello, Satya"
They are convenient, but they are also abstractions over simple character-by-character operations. Understanding what happens under the hood is not only fascinating but also extremely valuable for technical interviews.
Why developers write polyfills
A polyfill is a piece of code that provides modern functionality to older browsers that lack it. For example, String.prototype.includes was introduced in ES6 (2015). If you needed to support an environment that didn't have it, you would write your own version of includes and attach it to String.prototype (carefully, of course).
But even in modern development, writing polyfills serves another purpose: it forces you to truly understand how a method works. Interviewers love to ask, "Can you implement your own version of startsWith?" or "How would you write a polyfill for repeat?" Knowing the internal logic makes you a stronger developer and prepares you for these moments.
So, let's start building.
Implementing simple string utilities: polyfills
We will write our own versions of several common string methods. For each one, I'll explain the logic step by step and then show the code. Remember, these are simplified educational versions that aim to mimic the core behavior as per the MDN specification.
Polyfill for includes
The includes method determines whether one string can be found within another string, returning true or false. It takes a search string and an optional position from which to start searching. It is case-sensitive.
Logic: Loop through the main string from the given start position. For each index, check if the substring starting there matches the search string. If we find a full match, return true. If we reach the end without a match, return false.
if (!String.prototype.myIncludes) {
String.prototype.myIncludes = function(search, start) {
if (search instanceof RegExp) {
throw new TypeError("First argument must not be a RegExp");
}
start = start || 0;
if (start + search.length > this.length) return false;
return this.indexOf(search, start) !== -1;
};
}
Wait, we used indexOf above! That's cheating if we want a from-scratch polyfill without relying on other ES6 methods. So let's do a straight loop:
String.prototype.myIncludes = function(search, start) {
if (search instanceof RegExp) throw new TypeError("First argument must not be a RegExp");
start = start || 0;
var source = this;
while (start + search.length <= source.length) {
var match = true;
for (var i = 0; i < search.length; i++) {
if (source[start + i] !== search[i]) {
match = false;
break;
}
}
if (match) return true;
start++;
}
return false;
};
Now we have a pure implementation. The nested loop checks for character-by-character equality at each possible starting position.
Polyfill for startsWith
startsWith checks if a string begins with the characters of a specified string, returning true or false. It also accepts an optional position.
Logic: From the given position, compare the characters of the source string with the search string. If all match, return true. If any mismatch or if the remaining length is shorter than the search string, return false.
String.prototype.myStartsWith = function(searchString, position) {
position = position || 0;
if (position + searchString.length > this.length) return false;
for (var i = 0; i < searchString.length; i++) {
if (this[position + i] !== searchString[i]) {
return false;
}
}
return true;
};
This is straightforward: we just compare the two strings side by side from the starting index.
Polyfill for endsWith
endsWith checks if a string ends with the characters of a specified string, returning true or false. It accepts an optional length parameter, which sets the length of the string to consider. If not provided, it defaults to the full string length.
Logic: We need to compare the end of the source string (up to the given length) with the search string. The start index for comparison will be (length - searchString.length).
String.prototype.myEndsWith = function(searchString, length) {
var sourceLen = length !== undefined ? length : this.length;
if (sourceLen > this.length) sourceLen = this.length;
var startIndex = sourceLen - searchString.length;
if (startIndex < 0) return false;
for (var i = 0; i < searchString.length; i++) {
if (this[startIndex + i] !== searchString[i]) {
return false;
}
}
return true;
};
Test it:
console.log("Hello world".myEndsWith("world")); // true
console.log("Hello world".myEndsWith("Hello", 5)); // true
Polyfill for repeat
repeat constructs and returns a new string which contains the specified number of copies of the string on which it was called, concatenated together. It throws a RangeError if the count is negative or Infinity, and a count of zero returns an empty string.
Logic: We start with an empty string, then loop count times, appending the original string each time. However, for large counts, this would be inefficient. For a polyfill, a simple loop is fine as it's unlikely to be used with huge numbers in older browsers. But we can implement a more efficient method using doubling.
For simplicity, we'll do a loop and also handle non-integer counts by flooring them.
String.prototype.myRepeat = function(count) {
if (count < 0 || count === Infinity) {
throw new RangeError("Invalid count value");
}
count = Math.floor(count);
var result = "";
for (var i = 0; i < count; i++) {
result += this;
}
return result;
};
Test: "abc".myRepeat(3) gives "abcabcabc".
Polyfill for trim
trim removes whitespace from both ends of a string. Whitespace includes spaces, tabs, no-break spaces, and all line terminator characters.
Logic: Use a regular expression to strip leading and trailing whitespace. Alternatively, loop from the start and end to find the first non-whitespace character and slice the string.
A regex approach is simple and works in older environments:
String.prototype.myTrim = function() {
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "");
};
\s matches spaces, tabs, line breaks; \uFEFF is BOM (Byte Order Mark); \xA0 is non-breaking space. This closely matches the ES5 specification.
Common interview string problems and their logic
Beyond polyfills, interviews often test your ability to manipulate strings using basic algorithms. Here are a few classic problems, along with the thought process and solutions.
1. Reverse a string
Probably the most famous beginner question: "Write a function that reverses a string." The trick is to avoid using the built-in reverse method on arrays, at least in the explanation, but we can show multiple approaches.
Approach 1: Loop from end to start
function reverseString(str) {
var reversed = "";
for (var i = str.length - 1; i >= 0; i--) {
reversed += str[i];
}
return reversed;
}
Approach 2: Using array methods (built-in but still asked)
function reverseString(str) {
return str.split("").reverse().join("");
}
2. Check if a string is a palindrome
A palindrome reads the same forward and backward. You can use the reverse function and compare, but it's more efficient to compare characters from both ends moving inward.
function isPalindrome(str) {
str = str.toLowerCase().replace(/[^a-z0-9]/g, ""); // sanitize
var left = 0;
var right = str.length - 1;
while (left < right) {
if (str[left] !== str[right]) return false;
left++;
right--;
}
return true;
}
3. Count occurrences of a character or substring
A straightforward loop or using split:
function countChar(str, char) {
var count = 0;
for (var i = 0; i < str.length; i++) {
if (str[i] === char) count++;
}
return count;
}
// Using split trick (but not recommended for interviews if they want algorithm)
function countSubstring(str, sub) {
return str.split(sub).length - 1;
}
4. Truncate a string
Write a function that truncates a string to a given length and appends "..." if it was truncated.
function truncate(str, maxLength) {
if (str.length <= maxLength) return str;
return str.slice(0, maxLength) + "...";
}
5. Capitalize the first letter of each word
A classic transformation:
function capitalizeWords(str) {
return str.split(" ").map(function(word) {
if (word.length === 0) return word;
return word[0].toUpperCase() + word.slice(1).toLowerCase();
}).join(" ");
}
6. Remove duplicates from a string
We can use a Set, but interviewers might ask for a manual approach:
function removeDuplicates(str) {
var seen = {};
var result = "";
for (var i = 0; i < str.length; i++) {
if (!seen[str[i]]) {
seen[str[i]] = true;
result += str[i];
}
}
return result;
}
These exercises train you to think in loops and conditionals, which is exactly the skill needed to write polyfills or solve algorithmic challenges.
The importance of understanding built-in behavior
When you write a polyfill, you are essentially stepping into the shoes of the JavaScript engine. You learn to handle edge cases: what happens if the argument is a RegExp? What if the count is Infinity? How does case-sensitivity work? This depth of understanding makes you a safer and more precise developer.
In an interview, if you can not only use includes but also explain how it might be implemented and then code it up on a whiteboard, you demonstrate a fundamental command of the language that many candidates lack. It shows you don't just memorize methods; you understand principles.
Moreover, knowing the internal logic helps you debug mysterious bugs. For instance, understanding that trim removes a specific set of whitespace characters, not just spaces, prevents unexpected failures when dealing with user input.
Visualizing string processing flow
I often picture a string method as a loop with a pointer scanning across the characters. For includes, imagine a sliding window. You have the main string, and you slide the search string along it, checking each position until you find a match or reach the end.
For startsWith, you only look at the very beginning, like checking the first few letters of a book title to see if it matches a given prefix. For endsWith, you look at the last letters, moving your attention to the tail of the string.
For something like repeat, it's like a factory that takes a template and stamps out copies, joining them one after another. For trim, you walk in from both edges, trimming away whitespace until you hit a visible character, then capture the inner part.
This mental imagery makes writing polyfills much easier because you translate the visual into code.
Conclusion
Today we've gone beyond just using string methods and dug into the logic that powers them. We built polyfills for includes, startsWith, endsWith, repeat, and trim, seeing how simple loops and conditionals can replicate browser-native behavior. We also solved common interview string problems to reinforce the thinking pattern.
Let's summarize the key takeaways:
- String methods are built-in tools that manipulate strings, but they are all based on fundamental operations like looping, comparison, and slicing.
- Polyfills are implementations of modern methods that enable them in older environments, and writing them deepens your understanding of JavaScript.
- We created step-by-step polyfills for
includes,startsWith,endsWith,repeat, andtrim, each with a clear logic. - Interview problems like reversing a string, checking palindromes, counting occurrences, and capitalizing words rely on the same foundational skills.
- Truly comprehending built-in behavior prepares you for technical interviews and makes you a more effective developer.
The next time you use a string method, you'll know exactly what's happening behind the scenes, and you'll be ready to tackle any string-related challenge that comes your way.
Hope you found this helpful! If you spot any mistakes or have suggestions, let me know. You can find me on LinkedIn and X, where I post more about web development.

Top comments (0)