Skip to main content

Command Palette

Search for a command to run...

String Polyfills in JavaScript

Zero to Hero Interview Guide

Published
4 min read
String Polyfills in JavaScript

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;
};

JavaScript

Part 5 of 24

Master JavaScript from the ground up with a structured, easy-to-follow learning path designed for serious developers. This series starts with core fundamentals like variables, data types, and control flow, then gradually moves into deeper topics such as functions, scope, prototypes, asynchronous programming, and how the JavaScript engine works internally. Each lesson focuses on clarity and real understanding. You will learn not only how to write JavaScript, but why it behaves the way it does. Concepts are explained using simple examples, practical use cases, and clean coding patterns that reflect real-world development.

Up next

Map and Set in JavaScript

What is a Map? A Map is a collection of keyed data items, similar to an Object. However, the primary difference is that Map allows keys of any type functions, objects, or even primitives. Map vs Objec