# 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](https://github.com/Ritam369/Polyfills-Library-JS/blob/main/string-polyfills.js)), 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:

```javascript
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](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61lw04967xn1rdys90v7.png align="center")](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61lw04967xn1rdys90v7.png)

* * *

## **Why Developers Write Polyfills**

Polyfills are pure gold for three reasons:

1.  **Backward compatibility** — **older 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**

```javascript
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.

```javascript
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**

```javascript
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**

```javascript
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**

```javascript
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**

```javascript
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()`

```javascript
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**

```javascript
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()`

```javascript
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()`

```javascript
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**

```javascript
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()`

```javascript
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**

```javascript
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()`

```javascript
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()`

```javascript
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` |
