Strings and String Polyfills
A normal data structure that was defined for practical use. That is what strings are. But to me, strings are just more than that. If we consider the computer as a sentient alien, then strings are a medium it has created to communicate to us in our language. That is the kind of vibe strings give me in computers. And in this blog, we will treat strings with such respect. We will try to understand what strings actually are in JavaScript, what we can do with them, how common string operations work and common string manipulation problems.
Strings in JavaScript are immutable. This means that a string object cannot be modified under any circumstances. At best, we can reassign a variable or create a new string based on the old one, but we can never change the original string. This ensures effective memory management, prevents accidental change of data and safe reuse of values.
String Methods
Unlike many other languages, in JavaScript, strings are considered primitive data types. There are many built-in string functions for manipulating strings. Since strings are immutable, these methods always return a new String (if they are meant to manipulate data).
Let us look at some common string methods:
String.prototype.toUpperCase()
This method returns a new string in which each character is converted to uppercase.const ans = "Hello".toUpperCase(); //ans = "HELLO"String.prototype.toLowerCase()
This method returns a new string where each alphabet present in the character is converted into a lowercase alphabet.const ans = "Hello".toLowerCase(); //ans = "hello"String.prototype.trim()
This method returns a new string where the starting and ending spaces are removed.const ans = " Hello ".trim(); //ans = "Hello"String.prototype.includes()
This method takes a string and a starting position index as arguments. It starts searching from the starting position index and checks if the given string is a substring of that section of the string.const ans = " Hello ".includes('llo',0f); //ans = trueString.prototype.slice()
This method takes a starting position index and an ending position index as arguments. Including the starting index returns the segment of the string from the starting index to the ending index, where the ending index is not included. If the ending index is not provided, it returns the entire string from the starting index to the end.const ans = "Hello".slice(1,4); //ans = 'ell'String.prototype.substring()
Same as slice. Slice is preferred generally.const ans = "Hello".substring(1,4); //ans = 'ell'String.prototype.replace()
This method takes two arguments. A substring present in the string and a new string to replace that substring with. It only replaces the first occurrence. To replace all occurrences, we need the function - replaceAllconst ans = "Hello this JavaScript course is on JavaScript".replace('JavaScript','Go'); //ans = "Hello this Go course is on JavaScript"String.prototype.split()
This method takes one compulsory and one optional argument. The first argument defines a character, string or regex based on which the split should occur. The second argument limits the number of entries in the final output. Given these, this function creates segments of the given string and stores those segments in an array. By default, if no expression is provided, it returns the same string in an array. If no limit is provided, it returns all segments.const ans = "Hello this is a JavaScript Course" .split(' ',4); //ans = ['Hello','this','is','a'];
The above string functions are some of the most commonly used string functions. However, all of these functions may not be supported by some older versions of some browsers. This might cause logic mismatches across the codebase for the developers. To patch this gap, developers had to write polyfills.
Polyfills
Pollyfills basically mean - "I was so nostalgic about it that instead of being sad for missing it here, I created it myself". In technical language, a polyfill is a piece of code that is written by a developer to recreate a functionality in an older version of a system that doesn't support the functionality of the newer version. This allows for the code to be backwards compatible. And this also means that a developer must be able to understand how strings work internally so that they can recreate any function should the need arise.
To understand strings more deeply, practice polyfills, and to cover some common interview questions, let us look at some string polyfills and string problems.
The includes Function
if (!String.prototype.includes) {
String.prototype.includes = function(search) {
return this.indexOf(search) !== -1;
};
}
The reverse Function
function reverseStr(str){
let ans = "";
for(let i=str.length-1;i>=0;i--){
ans += str[i];
}
return ans;
}
The count vowels Function
function countVowels(str){
let c = 0;
let vowels = "aeiouAEIOU";
for(let ch of str){
if(vowels.includes(ch)) c++;
}
return c;
}
Some Interview Problems
Check Palindrome
function palindrome(str){
return str.split('').reverse().join('')===str;
}
Count Characters
function countCharacters(str){
const map = new Map();
for(let ch of str){
if(map.has(ch))
map.set(ch,map.get(ch)+1);
else
map.set(ch,1);
}
return map;
}
Anagram Check
function checkAnagram(str1,str2){
return (str1.split('').sort().join('')
===
str2.split('').sort().join(''));
}
Remove Duplicate Characters
function removeDuplicate(str){
const set = new Set(str.split(''));
return [...set].join('');
}
There are many such problems and functions in the world of strings in JavaScript. There are even multiple ways of defining a string using - double quotes (""), single quotes (''), backticks (``), using the String class constructor and more. We have many different string operations and features, like the evaluation of a string having an arithmetic expression, etc. One must study strings beyond their general usage to fully master them.