Skip to main content

Command Palette

Search for a command to run...

String Polyfills and Common Interview Methods in JavaScript

Updated
4 min readView as Markdown
String Polyfills and Common Interview Methods in JavaScript

1. Are String Methods?

In JavaScript, strings are primitive data types, but when you try to access a property or method on a string, JavaScript automatically wraps it in a temporary String object.

String methods are built-in functions attached to the String.prototype. They allow developers to manipulate, inspect, and extract text data easily without writing complex loops every time.

Common examples include:

  • Transformation: .toUpperCase(), .trim(), .replace()

  • Extraction: .slice(), .substring(), .split()

  • Inspection: .indexOf(), .includes(), .startsWith()

2. Why Developers Write Polyfills

A polyfill is a piece of code (usually JavaScript) used to provide modern functionality on older browsers that do not natively support it.

However, in the context of technical interviews, interviewers ask you to write polyfills for a completely different reason:

  1. To test first-principles thinking: Can you build the tool, or do you only know how to use it?

  2. To assess prototype knowledge: Do you understand how this works in the context of the String.prototype?

  3. To check edge-case handling: Do you remember to check for negative inputs, null, or undefined?

3. Implementing Simple String Utilities (Polyfills)

Let’s look at how built-in methods work conceptually by writing our own versions. When writing a polyfill, it is a best practice to check if the method already exists to avoid overwriting native behavior.

Example A: Polyfilling String.prototype.repeat()

The native .repeat(n) method returns a new string containing the original string repeated n times.

The Logic: Create an empty string, loop n times, append the context (this) to the result, and return it.

if (!String.prototype.customRepeat) {
  String.prototype.customRepeat = function(count) {
    // Edge case handling
    if (count < 0) throw new RangeError('Repeat count must be non-negative');
    if (count === Infinity) throw new RangeError('Repeat count must be less than infinity');
    
    let result = '';
    // 'this' refers to the string calling the method
    for (let i = 0; i < count; i++) {
      result += this; 
    }
    return result;
  };
}

console.log("hello ".customRepeat(3)); // "hello hello hello "

Example B: Polyfilling String.prototype.startsWith()

The native method checks if a string begins with the characters of a specified string.

The Logic: Iterate through the search string. If any character doesn't match the corresponding character at the beginning of the main string, return false.

if (!String.prototype.customStartsWith) {
  String.prototype.customStartsWith = function(searchString) {
    if (searchString.length > this.length) return false;
    
    for (let i = 0; i < searchString.length; i++) {
      if (this[i] !== searchString[i]) {
        return false;
      }
    }
    return true;
  };
}

console.log("javascript".customStartsWith("java")); // true

4. Common Interview String Problems

Interviewers often move from polyfills to algorithmic string problems. You are usually explicitly asked not to use built-in methods like .reverse() or .split().

  • Reverse a String:

    • The Trap: str.split('').reverse().join('') is easy, but it creates a new array in memory ($O(N)$ space).

    • The Solution: Iterate backward through the string using a for loop and concatenate characters to a new string.

  • Valid Palindrome Check:

    • The Logic: Use a "Two-Pointer" approach. Place one pointer at the start (index 0) and one at the end (length - 1). Check if they match, then move them toward the center. This is highly efficient ($O(N)$ time, $O(1)$ space).
  • Valid Anagrams:

    • The Logic: Create a "frequency map" (an object/hash map) that counts the occurrences of each character in the first string. Iterate through the second string and subtract the counts. If all counts hit zero, it's an anagram.

5. The Importance of Understanding Built-in Behavior

Knowing how these methods operate under the hood is critical for writing performant code.

For example: If you know that strings in JavaScript are immutable (they cannot be changed once created), you understand that every time you use .replace() or concatenate with +, JavaScript is actually destroying the old string and allocating memory for a brand-new one.

Understanding this prevents you from writing highly inefficient loops that concatenate massive strings character by character, and instead might lead you to push substrings into an array and .join('') them at the very end.