Skip to main content

Command Palette

Search for a command to run...

Mastering String Polyfills & Interview Methods in JavaScript

Published
β€’8 min read
Mastering String Polyfills & Interview Methods in JavaScript

Strings are absolutely everywhere in JavaScript. Whether you're capturing user input from a form, parsing an API response, or formatting data for the UI, you're constantly working with text.

While most developers know how to use built-in string methods, understanding how those methods actually work under the hood is what separates beginners from senior engineers.

In this guide, we'll dive deep into JavaScript string methods. We'll explore why you need string polyfills (especially for interviews!), implement some of the most common string functions from scratch, and walk through the classic string problems you're guaranteed to face in technical interviews.


πŸ“Œ A Quick Refresher: What Are String Methods?

String methods are the built-in JavaScript functions that allow us to easily manipulate and query text.

"hello".toUpperCase();   // Returns "HELLO"
"hello".includes("he");  // Returns true
"hello".slice(1, 4);     // Returns "ell"

The Golden Rule of Strings: Immutability

Before we go further, there's one critical concept you must remember: Strings in JavaScript are immutable. This means you cannot change a string once it's created. When you use a method like .toUpperCase(), it doesn't modify the original string; instead, it returns a brand new string.


πŸ€” Why Do We Write Polyfills?

A polyfill is essentially your own custom implementation of a built-in method. If a browser doesn't support a specific feature (like .includes() in older versions of Internet Explorer), a polyfill provides that missing functionality so your code doesn't break.

But more importantly for you right now: Interviewers love asking you to write polyfills.

Why? Because writing str.includes("a") is easy. Writing the logic that makes includes work proves you understand loops, conditions, and how strings are indexed in memory.


🧠 How Built-in Methods Work (Conceptually)

Let's demystify what happens when you call a string method. Imagine you use .includes().

"hello".includes("ll")

Under the hood, JavaScript isn't doing magic. It's following a logical set of steps:

  1. It loops through the characters of the original string.

  2. At every character, it compares a slice of the string to your search term.

  3. If it finds a match, it returns true. If the loop finishes without a match, it returns false.

Step 1: Check "he" β†’ No match
Step 2: Check "el" β†’ No match
Step 3: Check "ll" β†’ Match found! βœ… Return true.

Let's turn this theory into code.


πŸ”§ Polyfill 1: Recreating .includes()

Here is how you can write your own version of String.prototype.includes. By attaching it to the String.prototype, any string in our application can use this method.

if (!String.prototype.myIncludes) {
  String.prototype.myIncludes = function(search) {
    // We only need to loop up to the point where the remaining 
    // characters are less than the length of our search term
    for (let i = 0; i <= this.length - search.length; i++) {
      // Check if a slice of the current string matches the search term
      if (this.slice(i, i + search.length) === search) {
        return true;
      }
    }
    return false; // Loop finished, no match found
  };
}

console.log("hello world".myIncludes("world")); // true

βœ‚οΈ Polyfill 2: Recreating .slice()

The .slice() method extracts a section of a string and returns it as a new string, without modifying the original string. This one is a bit trickier because it allows for negative indexes!

if (!String.prototype.mySlice) {
  String.prototype.mySlice = function(start, end = this.length) {
    let result = "";

    // Handle negative indexes by wrapping around from the end
    if (start < 0) start = this.length + start;
    if (end < 0) end = this.length + end;

    // Loop from the start index up to the end index
    for (let i = start; i < end && i < this.length; i++) {
      result += this[i];
    }

    return result;
  };
}

console.log("JavaScript".mySlice(0, 4)); // "Java"

πŸ”„ Polyfill 3: Recreating .toUpperCase()

How does JavaScript know how to capitalize letters? It uses ASCII/Unicode values! Every character has an underlying numeric code.

if (!String.prototype.myToUpperCase) {
  String.prototype.myToUpperCase = function() {
    let result = "";

    for (let char of this) {
      const code = char.charCodeAt(0);

      // In ASCII, lowercase letters "a" to "z" are 97 through 122.
      // Uppercase letters "A" to "Z" are 65 through 90.
      // So, subtracting 32 from a lowercase code gives us the uppercase code!
      if (code >= 97 && code <= 122) {
        result += String.fromCharCode(code - 32);
      } else {
        result += char; // Keep punctuation and spaces unchanged
      }
    }

    return result;
  };
}

console.log("coding".myToUpperCase()); // "CODING"

🧩 Rapid Fire: Simple String Utilities

Interviewers will often ask you to implement these basic helper functions to warm up.

1. Reverse a String

The easiest way? Turn it into an array, reverse the array, and join it back together.

function reverse(str) {
  return str.split("").reverse().join("");
}

2. Check for a Palindrome

A palindrome reads the same forwards and backwards (like "racecar").

function isPalindrome(str) {
  return str === reverse(str);
}

3. Count Characters

Need to know how many times each letter appears? Use an object as a hash map!

function charCount(str) {
  const map = {};

  for (let char of str) {
    map[char] = (map[char] || 0) + 1;
  }

  return map;
}

πŸ’Ό The Heavyweights: Common Interview String Problems

Once you're warmed up, interviews will usually pivot to algorithmic string problems. Here are the classics.

1. Longest Substring Without Repeating Characters

The strategy: Use a "Sliding Window". You logically create a "window" of characters and expand it to the right. If you hit a duplicate character, you shrink the window from the left until the duplicate is removed.

2. Anagram Check

An anagram is a word formed by rearranging the letters of another (e.g., "listen" and "silent"). The strategy: Sort both strings. If they are identical after sorting, they are anagrams!

function isAnagram(a, b) {
  return a.split("").sort().join("") === b.split("").sort().join("");
}

3. First Non-Repeating Character

The strategy: Use a hash map to count character frequencies, then loop through the string one more time to find the first character with a count of 1.

function firstUnique(str) {
  const map = {};

  // Build the frequency map
  for (let char of str) {
    map[char] = (map[char] || 0) + 1;
  }

  // Find the first unique character
  for (let char of str) {
    if (map[char] === 1) return char;
  }
  
  return null;
}

4. String Compression

Turn "AAABBCC" into "A3B2C2". The strategy: Iterate through the string, keeping a running count of the current character. When the character changes, append the letter and its count to your result string, then reset the count.

function compress(str) {
  let result = "";
  let count = 1;

  for (let i = 1; i <= str.length; i++) {
    if (str[i] === str[i - 1]) {
      count++;
    } else {
      result += str[i - 1] + count;
      count = 1; // Reset counter for the new character
    }
  }

  return result;
}

⚑ Time Complexity Quick Sheet

When discussing these solutions, you must be able to talk about Big O notation.

Problem Time Complexity Note
Reverse string O(n) We must visit every character once.
Anagram check O(n log n) The bottleneck here is the .sort() method.
Character count O(n) Looping through the string takes linear time.
Compression O(n) A single pass through the string.

πŸ“‰ Common Mistakes to Avoid

When live-coding string problems, watch out for these traps: ❌ Forgetting Immutability: Trying to change a string directly (e.g., str[0] = "X") will fail silently. ❌ Missing Edge Cases: Always consider what happens if they pass you an empty string "" or surprisingly large inputs. ❌ Using Forbidden Methods: If the interviewer asks for an anagram check, make sure they allow .sort(). Sometimes they want a hash map approach instead! ❌ Forgetting ASCII: When manipulating cases or shifting letters, remembering .charCodeAt() is a lifesaver.


🏁 Final Thoughts

Understanding string polyfills and algorithms gives you a massive advantage. It demonstrates deep language knowledge, flexes your problem-solving muscles, and prepares you for the exact questions top tech companies ask.

πŸ’¬ Your Action Item:

Don't just read this. Open up a blank file. Practice writing .includes(), .slice(), and .toUpperCase() from scratch, without looking at the code. Once you can do that comfortably, you'll be unstumpable in your next interview! πŸš€

JavaScript Decoded

Part 1 of 9

JavaScript Decoded is a step-by-step blog series designed for beginners and self-taught developers who want to truly understand JavaScript from the ground up. Each post covers one core concept β€” variables, control flow, functions, arrays, objects, and more β€” with practical code examples, beginner-friendly explanations, and tips you can apply right away. No fluff, just clarity.

Up next

πŸš€ Mastering Array Flattening in JavaScript: From Built-ins to Custom Polyfills

If you've spent any time working with JavaScript, you've probably encountered a situation where you had an array filled with other arrays, and you just wanted one clean, flat list. Flattening arrays i