String Polyfills in JavaScript
Zero to Hero Interview Guide

What are string methods?
In JavaScript, strings come with a powerful set of built-in methods functions attached to every string value that let you search, transform, slice, and inspect text. When you call "hello".toUpperCase(), you're using a method that JavaScript's engine provides automatically. These aren't magic; they're functions defined on String.prototype, the shared blueprint that every string inherits from.
The key insight for interview preparation is this: knowing what a method does isn't enough. Interviewers want to know how it works and whether you could rebuild it from scratch. That's where polyfills come in.
Why developers write polyfills
A polyfill is a piece of code that implements a feature that the current runtime doesn't support or that you're implementing yourself to demonstrate understanding. When a new string method lands in the JavaScript specification, older browsers don't have it. Developers write polyfills to bridge that gap, attaching the implementation directly to String.prototype before the browser's built-in version would run.
But in interviews, polyfills serve a different purpose. They force you to reason about the logic behind familiar tools. Can you write trim() without calling trim()? Can you implement includes() using only index-based access? These questions reveal how deeply you understand strings as sequences of characters.
Here's how the string processing model works under the hood:
One important detail the diagram highlights: strings in JavaScript are immutable. No string method ever modifies the original string.
Implementing simple string utilities as polyfills
Before writing a polyfill, always check if the method already exists. This prevents overwriting the native implementation in environments that support it.
if (!String.prototype.customTrim) {
String.prototype.customTrim = function () {
// `this` refers to the string value the method is called on
let start = 0;
let end = this.length - 1;
while (start <= end && this[start] === ' ') start++;
while (end >= start && this[end] === ' ') end--;
return this.slice(start, end + 1);
};
}
The logic here is a two-pointer approach.
Advance from the left until you hit a non-space character, retreat from the right until you hit a non-space character, then slice out the middle. This is exactly the kind of thinking interviews test: can you express a simple operation in terms of indices and comparisons?
Here's how the polyfill checking behavior works visually:
Common interview string methods to implement
includes(searchStr)
The built-in method checks whether a substring exists anywhere in the string, returning true or false. The polyfill uses a sliding window: at every position, compare the next searchStr.length characters against the target.
String.prototype.myIncludes = function (searchStr) {
const str = String(this);
const search = String(searchStr);
if (search.length === 0) return true;
if (search.length > str.length) return false;
for (let i = 0; i <= str.length - search.length; i++) {
if (str.slice(i, i + search.length) === search) return true;
}
return false;
};
Note the edge cases: an empty search string always returns true (this matches the spec), and a search string longer than the source immediately returns false.
repeat(count)
This builds a new string by concatenating the original count times.
String.prototype.myRepeat = function (count) {
const n = Math.floor(count);
if (n < 0 || n === Infinity) throw new RangeError('Invalid count value');
let result = '';
for (let i = 0; i < n; i++) result += this;
return result;
};
startsWith(prefix) and endsWith(suffix)
These are slice comparisons at fixed positions:
String.prototype.myStartsWith = function (prefix) {
return this.slice(0, prefix.length) === prefix;
};
String.prototype.myEndsWith = function (suffix) {
if (suffix.length === 0) return true;
return this.slice(-suffix.length) === suffix;
};
padStart(targetLength, padStr) and padEnd()
Padding methods fill the string until it reaches a desired length:
String.prototype.myPadStart = function (targetLength, padStr = ' ') {
const str = String(this);
if (str.length >= targetLength) return str;
const padNeeded = targetLength - str.length;
let padding = '';
while (padding.length < padNeeded) padding += padStr;
return padding.slice(0, padNeeded) + str;
};





