Skip to main content

Command Palette

Search for a command to run...

String Polyfills & Common Interview Methods in JavaScript

Updated
8 min readView as Markdown
String Polyfills & Common Interview Methods in JavaScript

Introduction: Why String Manipulation Still Matters

Imagine this: You’re in a high-stakes JavaScript interview. The interviewer leans in and says, “Implement trim(), replaceAll(), and split() from scratch — no built-ins allowed.” Your pulse quickens… but then you smile. Because you’ve already read my blog, so no worries at all!

String methods are like everyday needs of JavaScript. They power form validation, data cleaning, URL parsing, and almost every dynamic UI you’ve ever built. Yet most developers treat them as magic.

In this complete guide, we’ll break them down completely: what string methods really are, why polyfills are essential, a full deep-dive into all 15 string polyfills I personally wrote (available in my Polyfills Library on GitHub), the most common interview problems, and — most importantly — the exact logic behind every built-in so you can think like the JavaScript engine itself.

Let’s turn “it just works” into “I know exactly how it works.”


What Are String Methods in JavaScript?

String methods are functions that are attached to String.prototype. When you call "ritam".toUpperCase(), JavaScript is secretly doing:

String.prototype.toUpperCase = function() { /* native optimized code */ };

Key concepts every developer should internalize:

  • Strings in JavaScript are immutable — every method returns a new string.

  • Most methods loop through characters (or use fast native shortcuts).

  • They operate on this (the current string instance).

  • Common categories: inspection (includes, indexOf), transformation (trim, replace), extraction (slice, substring), and utility (repeat, padStart).

Understanding this flow is your foundation for writing perfect polyfills.

Processing flow


Why Developers Write Polyfills

Polyfills are pure gold for three reasons:

  1. Backward compatibilityolder browsers or restricted environments might not have replaceAll, at(), etc.

  2. Deep learning — writing a polyfill forces you to understand the exact algorithm the browser uses. It builds the thought process of every developer.

  3. Interview dominance — interviewers specifically ask you to implement these from scratch to test real understanding.

Polyfills turn you from a user of JavaScript into an engineer who knows the language inside-out.


Implementing All String Utilities – My Complete Polyfill Library

Here are all 15 polyfills exactly as I wrote them, with detailed explanations of the logic, how they mimic built-in behavior, and why the implementation matters for interviews.

1. firstCap() – Capitalize first letter using ASCII math

String.prototype.firstCap = function() {
    let charCode = this.charCodeAt(0);
    if(charCode >= 97 && charCode <= 122) {
        return String.fromCharCode(charCode - 32) + this.slice(1);
    }
    return this;
};

Logic & Interview Insight: Pure ASCII manipulation. Lowercase letters are 97-122; subtract 32 to get uppercase. No toUpperCase() used — shows you understand character encoding. The String.fromCharCode() static method returns a string created from the specified sequence of UTF-16 code units. Perfect for “capitalize without built-ins” questions.

String.prototype.lastCap = function() {
    let charCode = this.charCodeAt(this.length - 1);
    if(charCode >= 97 && charCode <= 122) {
        return this.slice(0, this.length - 1) + String.fromCharCode(charCode - 32);
    }
    return this;
};

Logic: Same ASCII trick but targets the final character. Teaches precise index handling.

3. padBetween() – Insert a separator between every character

String.prototype.padBetween = function(pad) {
    let result = "";
    for(let i=0; i<this.length; i++) {
        result = result + this[i] + (i<this.length-1 ? pad : "");
    }
    return result;
};

Logic: Builds a new string while adding the pad only between characters. Great interview question for “insert separator without split + join”.

4. reverse() – Classic reversal

String.prototype.reverse = function() {
    let newString = "";
    for(let i=this.length-1; i>=0; i--) {
        newString = newString + this[i];
    }
    return newString;
};

Logic: Backward iteration + concatenation. Interviewers expect this exact pattern (or two-pointer in-place for arrays).

5. remove() – Remove all occurrences of a character

String.prototype.replaceBy = function(search, replace) {
    let newString = "";
    let searchLength = search.length;
    for(let i=0; i<this.length; i++) {
        if(this.slice(i, i+searchLength) === search) {
            newString = newString + replace;
            i = i + searchLength - 1;
        } else {
            newString = newString + this[i];
        }
    }
    return newString;
};

Logic: Sliding window comparison using slice. Foundation for understanding replaceAll.

6. replaceBy() – Custom replace

String.prototype.replaceBy = function(search, replace) {
    let newString = "";
    let searchLength = search.length;
    for(let i=0; i<this.length; i++) {
        if(this.slice(i, i+searchLength) === search) {
            newString = newString + replace;
            i = i + searchLength - 1;
        } else {
            newString = newString + this[i];
        }
    }
    return newString;
};

Logic: Sliding window comparison using slice. Foundation for understanding replaceAll.

7. include() – Custom includes()

String.prototype.include = function(search) {
    for(let i=0; i<this.length; i++) {
        if(this.slice(i, i+search.length) === search) {
            return true;
        }
    }
    return false;
};

Logic: Exact substring matching loop. Early return on match.

8. concatinate() – Safe concatenation

String.prototype.concatinate = function(separator, newStr) {
    return this + separator + newStr;
};

Logic: Simple but demonstrates chaining with other polyfills (see example in repo).

9. repeatString() – Custom repeat()

String.prototype.repeatString = function(count) {
    let result = "";
    for(let i=0; i<count; i++) {
        result = result + this;
    }
    return result;
};

Logic: Loop-based repetition. Shows why repeat() is O(n × count).

10. subString() – Custom substring()

String.prototype.subString = function(start, end){
    let result = "";
    while(start < end && start < this.length) {
        result = result + this[start];
        start++;
    }
    return result;
};

Logic: Boundary-safe extraction with manual loop.

11. sliceUp() – Custom slice() with optional delete + insert

String.prototype.sliceUp = function(start, deleteCount, insertStr) {
    let result = "";
    for(let i=0; i<start; i++) {
        result += this[i];
    }
    for(let i=0; i<insertStr.length; i++) {
        result += insertStr[i];
    }
    for(let i=start+deleteCount; i<this.length; i++) {
        result += this[i];
    }
    return result;
};

Logic: Three-phase build: prefix + insert + suffix. Extremely useful in interview “edit string at index” problems.

12. splitUp() – Full custom split()

String.prototype.splitUp = function(separator) {
    let result = [];
    if(separator === "")
        return Array.from(this);
    else{
        if(!this.include(separator)) {
            result.push(this);
        } else {
            let targetIndex = this.indexOf(separator);
            let item = "";
            for(let i=0; i<this.length; i++) {
                if(i === targetIndex) {
                    result.push(item);
                    item = "";
                    targetIndex = this.indexOf(separator, targetIndex+1);
                } else {
                    item += this[i];
                }
            }
            result.push(item);
        }
    }
    return result;
}

Logic: Handles empty separator + multiple occurrences using include() and index tracking.

13. joinUp() – Custom join() on Array.prototype

Array.prototype.joinUp = function(separator) {
    if(this.length === 0) return this.toString();
    let result = "";
    for(let i=0; i<this.length; i++) {
        result += (this[i] + (i<this.length-1 ? separator : ""));
    }
    return result;
};

Logic: Pairs perfectly with splitUp — the classic interview combo.

14. trimmer() – Custom trim()

String.prototype.trimmer = function() {
    let start = 0, end = this.length-1;
    while(this[start] === " ") start++;
    while(this[end] === " ") end--;
    return this.slice(start, end+1);
};

Logic: Two-pointer inward scan. Most elegant O(n) trim implementation.

15. toUpper() – Custom toUpperCase()

String.prototype.toUpper = function() {
    let result = "";
    for(let i=0; i<this.length; i++) {
        let charCode = this.charCodeAt(i);
        if(charCode >= 97 && charCode <= 122) {
            result += String.fromCharCode(charCode - 32);
        } else {
            result += this[i];
        }
    }
    return result;
};

Logic: Full ASCII conversion for every character. Complete understanding of case conversion.

Common Interview String Problems (Solved with These Polyfills)

  • Reverse a string → reverse()

  • Trim whitespace → trimmer()

  • Replace all occurrences → replaceBy() + loop

  • Split and join custom → splitUp() + joinUp()

  • Capitalize first/last → firstCap() / lastCap()

  • Remove characters → remove()

  • Check substring → include()

  • Insert between chars → padBetween()

Always mention time complexity (usually O(n)) and immutability in your explanation.

Importance of Understanding Built-in Behavior

When you’ve written these 15 polyfills, you no longer guess — you know. You debug faster, write more efficient code, and impress interviewers by explaining the exact algorithm the browser uses.

Why developers write polyfills

Developers write polyfills to make modern JavaScript features work in older browsers or environments that do not support them.

Common String Methods

Method Purpose Example
toUpperCase() Converts text to uppercase "hello".toUpperCase()"HELLO"
toLowerCase() Converts text to lowercase "HELLO".toLowerCase()"hello"
trim() Removes spaces from both ends " Hello ".trim()"Hello"
includes() Checks if a string contains specific text "Hello World".includes("World")true
startsWith() Checks how a string starts "Hello".startsWith("He")true
endsWith() Checks how a string ends "Hello".endsWith("lo")true
indexOf() Finds the position of text "Hello".indexOf("e")1
charAt() Returns a character at a position "Hello".charA