Comparing two strings character by character in JavaScript is a fundamental task in various programming scenarios, and COMPARE.EDU.VN offers a comprehensive guide to mastering this technique. This article dives deep into the methods, applications, and best practices of character-by-character string comparison in JavaScript, providing a reliable way to determine string similarity and enhance data manipulation skills, offering insights on string comparison techniques and JavaScript string methods.
1. Understanding the Basics of String Comparison in JavaScript
At its core, string comparison involves examining individual characters within two strings to determine their similarities or differences. This process is crucial for tasks such as validating user input, searching for specific patterns, and implementing advanced algorithms. In JavaScript, strings are sequences of Unicode characters, and character-by-character comparison allows for precise control over the comparison process.
1.1 What is Character-by-Character String Comparison?
Character-by-character string comparison is a method of comparing two strings by examining each character in sequence. This approach allows developers to identify exact matches, differences, and the degree of similarity between strings. This technique is essential for applications requiring precise string analysis.
1.2 Why Use Character-by-Character Comparison?
There are several reasons to use character-by-character comparison:
- Precision: It offers the highest level of precision when comparing strings.
- Control: It allows developers to control the comparison process and implement custom logic.
- Flexibility: It can be adapted to various string manipulation tasks.
- Algorithm Implementation: It is necessary for implementing complex algorithms like Levenshtein distance or custom pattern matching.
2. Methods for Comparing Strings Character by Character in JavaScript
JavaScript provides several methods for comparing strings character by character, each with its own advantages and use cases. Let’s explore the most common techniques.
2.1 Using for
Loops
The most straightforward method involves using for
loops to iterate over each character in the strings. This approach provides complete control over the comparison process.
function compareStringsCharacterByCharacter(str1, str2) {
if (str1.length !== str2.length) {
return false; // Strings of different lengths cannot be identical
}
for (let i = 0; i < str1.length; i++) {
if (str1[i] !== str2[i]) {
return false; // Characters at index i are different
}
}
return true; // All characters are identical
}
// Example usage
const string1 = "hello";
const string2 = "hello";
const string3 = "world";
console.log(compareStringsCharacterByCharacter(string1, string2)); // Output: true
console.log(compareStringsCharacterByCharacter(string1, string3)); // Output: false
This function, compareStringsCharacterByCharacter
, first checks if the lengths of the two strings are equal. If they are not, the function immediately returns false
because strings of different lengths cannot be identical. If the lengths are equal, the function iterates through each character of the strings using a for
loop. Inside the loop, it compares the characters at the current index i
in both strings. If it finds any characters that are not equal, the function immediately returns false
. If the loop completes without finding any mismatched characters, the function returns true
, indicating that all characters in both strings are identical.
2.2 Using while
Loops
Similar to for
loops, while
loops can be used to iterate through strings and compare characters.
function compareStringsWithWhile(str1, str2) {
let i = 0;
while (i < str1.length && i < str2.length) {
if (str1[i] !== str2[i]) {
return false;
}
i++;
}
return str1.length === str2.length; // Ensure both strings have the same length
}
// Example usage
const string1 = "test";
const string2 = "test";
const string3 = "rest";
console.log(compareStringsWithWhile(string1, string2)); // Output: true
console.log(compareStringsWithWhile(string1, string3)); // Output: false
This function, compareStringsWithWhile
, initializes a counter i
to 0. The while
loop continues as long as i
is less than the length of both str1
and str2
. Inside the loop, it compares the characters at the current index i
in both strings. If it finds any characters that are not equal, the function immediately returns false
. After the loop, the function checks if the lengths of str1
and str2
are equal using str1.length === str2.length
. This ensures that the function returns false
if one string is a prefix of the other but not identical.
2.3 Using Recursion
Recursion can also be employed to compare strings character by character. This method involves a function calling itself to compare subsequent characters.
function compareStringsRecursively(str1, str2, index = 0) {
if (index === str1.length && index === str2.length) {
return true; // Both strings have been fully compared
}
if (index >= str1.length || index >= str2.length) {
return false; // One string is shorter than the other
}
if (str1[index] !== str2[index]) {
return false; // Characters at the current index are different
}
return compareStringsRecursively(str1, str2, index + 1); // Recursive call to compare the next characters
}
// Example usage
const string1 = "coding";
const string2 = "coding";
const string3 = "code";
console.log(compareStringsRecursively(string1, string2)); // Output: true
console.log(compareStringsRecursively(string1, string3)); // Output: false
In this recursive function, compareStringsRecursively
, the base cases are when the index reaches the end of both strings (returning true
) or when one string is shorter than the other (returning false
). If the characters at the current index are different, the function returns false
. Otherwise, it makes a recursive call to compare the next characters by incrementing the index.
2.4 Using String.prototype.charAt()
The charAt()
method returns the character at a specified index in a string. It can be used in conjunction with loops for character-by-character comparison.
function compareStringsWithCharAt(str1, str2) {
if (str1.length !== str2.length) {
return false;
}
for (let i = 0; i < str1.length; i++) {
if (str1.charAt(i) !== str2.charAt(i)) {
return false;
}
}
return true;
}
// Example usage
const string1 = "example";
const string2 = "example";
const string3 = "sample";
console.log(compareStringsWithCharAt(string1, string2)); // Output: true
console.log(compareStringsWithCharAt(string1, string3)); // Output: false
This function, compareStringsWithCharAt
, checks if the lengths of the two strings are equal. If not, it returns false
. It then iterates through the strings using a for
loop, comparing characters at each index using charAt()
. If any characters are different, it returns false
. If the loop completes without finding any differences, it returns true
.
2.5 Using String.prototype.codePointAt()
The codePointAt()
method returns the Unicode value of the character at a specified index in a string. This method is useful when dealing with Unicode characters beyond the basic multilingual plane (BMP).
function compareStringsWithCodePointAt(str1, str2) {
if (str1.length !== str2.length) {
return false;
}
for (let i = 0; i < str1.length; i++) {
if (str1.codePointAt(i) !== str2.codePointAt(i)) {
return false;
}
}
return true;
}
// Example usage
const string1 = "😊test";
const string2 = "😊test";
const string3 = "😞test";
console.log(compareStringsWithCodePointAt(string1, string2)); // Output: true
console.log(compareStringsWithCodePointAt(string1, string3)); // Output: false
This function, compareStringsWithCodePointAt
, is similar to the compareStringsWithCharAt
function but uses codePointAt()
to handle Unicode characters properly. It checks if the lengths of the strings are equal and then iterates through each character, comparing their Unicode values. If any values are different, it returns false
. If the loop completes without finding any differences, it returns true
.
3. Advanced String Comparison Techniques
Beyond basic character-by-character comparison, there are advanced techniques that allow for more sophisticated string analysis.
3.1 Implementing Levenshtein Distance
Levenshtein distance (edit distance) measures the similarity between two strings by counting the minimum number of single-character edits required to change one string into the other.
function levenshteinDistance(str1, str2) {
const matrix = Array(str2.length + 1).fill(null).map(() =>
Array(str1.length + 1).fill(null)
);
for (let i = 0; i <= str1.length; i++) {
matrix[0][i] = i;
}
for (let j = 0; j <= str2.length; j++) {
matrix[j][0] = j;
}
for (let j = 1; j <= str2.length; j++) {
for (let i = 1; i <= str1.length; i++) {
if (str2[j - 1] === str1[i - 1]) {
matrix[j][i] = matrix[j - 1][i - 1];
} else {
matrix[j][i] = Math.min(
matrix[j - 1][i - 1] + 1, // Substitution
matrix[j][i - 1] + 1, // Insertion
matrix[j - 1][i] + 1 // Deletion
);
}
}
}
return matrix[str2.length][str1.length];
}
// Example usage
const string1 = "kitten";
const string2 = "sitting";
console.log(levenshteinDistance(string1, string2)); // Output: 3
This function calculates the Levenshtein distance between two strings. It initializes a matrix to store the distances between prefixes of the two strings. The first row and column are initialized with the distances from the empty string. The function then iterates through the matrix, calculating the distance between each pair of prefixes. If the characters at the current positions are equal, the distance is the same as the distance between the previous prefixes. Otherwise, the distance is the minimum of the distances for substitution, insertion, and deletion, plus one.
3.2 Using the Jaro-Winkler Distance
The Jaro-Winkler distance is a measure of similarity between two strings, accounting for the number and order of common characters.
function jaroWinklerDistance(str1, str2) {
const jaroDistance = calculateJaroDistance(str1, str2);
// Winkler Modification
let prefixLength = 0;
for (let i = 0; i < Math.min(str1.length, str2.length); i++) {
if (str1[i] === str2[i]) {
prefixLength++;
} else {
break;
}
}
const prefixScalingFactor = 0.1;
const winklerDistance = jaroDistance + (prefixLength * prefixScalingFactor * (1 - jaroDistance));
return winklerDistance;
}
function calculateJaroDistance(str1, str2) {
const matchWindow = Math.floor(Math.max(str1.length, str2.length) / 2) - 1;
let matches = 0;
const str1Matches = Array(str1.length).fill(false);
const str2Matches = Array(str2.length).fill(false);
for (let i = 0; i < str1.length; i++) {
const start = Math.max(0, i - matchWindow);
const end = Math.min(str2.length - 1, i + matchWindow);
for (let j = start; j <= end; j++) {
if (str1[i] === str2[j] && !str2Matches[j]) {
str1Matches[i] = true;
str2Matches[j] = true;
matches++;
break;
}
}
}
if (matches === 0) {
return 0;
}
let transpositions = 0;
let k = 0;
for (let i = 0; i < str1.length; i++) {
if (str1Matches[i]) {
while (!str2Matches[k]) {
k++;
}
if (str1[i] !== str2[k]) {
transpositions++;
}
k++;
}
}
const jaro = (matches / str1.length + matches / str2.length + (matches - transpositions / 2) / matches) / 3;
return jaro;
}
// Example usage
const string1 = "MARTHA";
const string2 = "MARHTA";
console.log(jaroWinklerDistance(string1, string2)); // Output: 0.9611111111111111
The jaroWinklerDistance
function first calculates the Jaro distance between the two strings using the calculateJaroDistance
function. The calculateJaroDistance
function identifies matching characters within a specified match window and calculates the number of transpositions. The Jaro distance is then computed based on the number of matches, transpositions, and the lengths of the strings.
The jaroWinklerDistance
function then applies the Winkler modification to adjust the Jaro distance based on the length of the common prefix. The Winkler modification increases the similarity score if the strings have a common prefix, reflecting the intuition that strings with common prefixes are more similar.
3.3 Using Regular Expressions for Pattern Matching
Regular expressions provide a powerful way to search and match patterns within strings. They can be used for complex string comparisons and validations.
function stringMatchesPattern(str, pattern) {
const regex = new RegExp(pattern);
return regex.test(str);
}
// Example usage
const string = "The quick brown fox";
const pattern = "quick.*fox";
console.log(stringMatchesPattern(string, pattern)); // Output: true
This function, stringMatchesPattern
, takes a string and a regular expression pattern as input. It creates a new RegExp
object with the given pattern and uses the test()
method to check if the string matches the pattern. The test()
method returns true
if the string matches the pattern and false
otherwise.
4. Practical Applications of Character-by-Character String Comparison
Character-by-character string comparison is used in various applications, from simple data validation to complex algorithm implementations.
4.1 Data Validation
Ensuring that user input matches a specific format often involves character-by-character comparison. For example, validating email addresses, phone numbers, or postal codes requires precise pattern matching.
function isValidEmail(email) {
const pattern = /^[^s@]+@[^s@]+.[^s@]+$/;
return pattern.test(email);
}
// Example usage
const email1 = "[email protected]";
const email2 = "invalid-email";
console.log(isValidEmail(email1)); // Output: true
console.log(isValidEmail(email2)); // Output: false
This function, isValidEmail
, validates an email address using a regular expression pattern. The pattern checks for the presence of non-whitespace characters before and after the @
symbol, as well as a period (.
) followed by more non-whitespace characters. The test()
method returns true
if the email address matches the pattern and false
otherwise.
4.2 Text Search and Pattern Matching
Searching for specific patterns within large text documents often requires character-by-character comparison. This is commonly used in text editors, search engines, and data analysis tools.
function findOccurrences(text, pattern) {
const regex = new RegExp(pattern, 'g');
let matches = [];
let match;
while ((match = regex.exec(text)) !== null) {
matches.push(match.index);
}
return matches;
}
// Example usage
const text = "This is a test string with test occurrences.";
const pattern = "test";
console.log(findOccurrences(text, pattern)); // Output: [ 10, 26 ]
This function, findOccurrences
, finds all occurrences of a given pattern in a text string. It creates a regular expression with the global flag g
to find all matches. The exec()
method is used in a while
loop to find each match, and the index of each match is added to the matches
array. The function returns an array of the indices where the pattern occurs in the text.
4.3 Implementing Spell Checkers
Spell checkers use algorithms like Levenshtein distance to suggest corrections for misspelled words.
function suggestCorrections(word, dictionary) {
const suggestions = [];
for (const dictWord of dictionary) {
const distance = levenshteinDistance(word, dictWord);
if (distance <= 2) {
suggestions.push({ word: dictWord, distance: distance });
}
}
suggestions.sort((a, b) => a.distance - b.distance);
return suggestions.map(suggestion => suggestion.word);
}
// Example usage
const word = "hte";
const dictionary = ["the", "hat", "hit", "hot"];
console.log(suggestCorrections(word, dictionary)); // Output: [ 'the', 'hat', 'hit' ]
This function, suggestCorrections
, suggests corrections for a misspelled word by comparing it to words in a dictionary. It calculates the Levenshtein distance between the misspelled word and each word in the dictionary. If the distance is less than or equal to 2, the dictionary word is considered a suggestion. The suggestions are sorted by their Levenshtein distance, and the function returns an array of suggested words.
4.4 Bioinformatics and Genetic Sequencing
Character-by-character comparison is essential in bioinformatics for analyzing DNA and RNA sequences.
function dnaSequenceAlignment(seq1, seq2) {
// Simplified alignment scoring
const matchScore = 1;
const mismatchScore = -1;
const gapPenalty = -2;
// Initialize scoring matrix
const matrix = Array(seq2.length + 1).fill(null).map(() => Array(seq1.length + 1).fill(0));
// Fill the matrix
for (let i = 1; i <= seq1.length; i++) {
for (let j = 1; j <= seq2.length; j++) {
const match = matrix[j - 1][i - 1] + (seq1[i - 1] === seq2[j - 1] ? matchScore : mismatchScore);
const deleteGap = matrix[j - 1][i] + gapPenalty;
const insertGap = matrix[j][i - 1] + gapPenalty;
matrix[j][i] = Math.max(match, deleteGap, insertGap);
}
}
// Traceback to find the alignment (simplified)
let alignment1 = "";
let alignment2 = "";
let i = seq1.length;
let j = seq2.length;
while (i > 0 && j > 0) {
const score = matrix[j][i];
const match = matrix[j - 1][i - 1] + (seq1[i - 1] === seq2[j - 1] ? matchScore : mismatchScore);
const deleteGap = matrix[j - 1][i] + gapPenalty;
const insertGap = matrix[j][i - 1] + gapPenalty;
if (score === match) {
alignment1 = seq1[i - 1] + alignment1;
alignment2 = seq2[j - 1] + alignment2;
i--;
j--;
} else if (score === deleteGap) {
alignment1 = "-" + alignment1;
alignment2 = seq2[j - 1] + alignment2;
j--;
} else {
alignment1 = seq1[i - 1] + alignment1;
alignment2 = "-" + alignment2;
i--;
}
}
return { alignment1, alignment2, score: matrix[seq2.length][seq1.length] };
}
// Example usage
const sequence1 = "ACGT";
const sequence2 = "AGGT";
console.log(dnaSequenceAlignment(sequence1, sequence2));
// Expected Output (may vary based on alignment choices):
// {
// alignment1: 'ACGT',
// alignment2: 'A-GT',
// score: 1
// }
This function, dnaSequenceAlignment
, performs a simplified sequence alignment of two DNA sequences using a scoring matrix. It calculates the alignment score based on match, mismatch, and gap penalties. The function then traces back through the matrix to construct the aligned sequences, inserting gaps where necessary to maximize the alignment score. The result is an object containing the aligned sequences and the overall alignment score.
5. Performance Considerations
While character-by-character string comparison offers precision and control, it’s essential to consider performance implications, especially when dealing with large strings.
5.1 Optimizing Loop-Based Comparisons
For loop-based comparisons, consider the following optimizations:
- Early Exit: If a mismatch is found, exit the loop immediately to avoid unnecessary iterations.
- Length Check: Ensure strings are of equal length before starting the comparison.
- Minimize Function Calls: Reduce the number of function calls within the loop.
5.2 Using Built-in Methods
JavaScript’s built-in string methods like charAt()
and codePointAt()
are generally optimized for performance. Use them judiciously to improve efficiency.
5.3 When to Use Advanced Techniques
Advanced techniques like Levenshtein distance and Jaro-Winkler distance are computationally intensive. Use them only when necessary and consider memoization or caching to improve performance for repeated calculations.
6. Case Studies: Real-World Examples
Let’s examine real-world examples where character-by-character string comparison is crucial.
6.1 Implementing a Code Editor with Syntax Highlighting
Code editors use character-by-character comparison to identify keywords, operators, and other syntax elements for syntax highlighting.
function syntaxHighlight(code, keywords) {
let highlightedCode = "";
let currentWord = "";
for (let i = 0; i < code.length; i++) {
const char = code[i];
if (/[a-zA-Z0-9]/.test(char)) {
currentWord += char;
} else {
if (keywords.includes(currentWord)) {
highlightedCode += `<span class="keyword">${currentWord}</span>`;
} else {
highlightedCode += currentWord;
}
highlightedCode += char;
currentWord = "";
}
}
// Handle the last word
if (keywords.includes(currentWord)) {
highlightedCode += `<span class="keyword">${currentWord}</span>`;
} else {
highlightedCode += currentWord;
}
return highlightedCode;
}
// Example usage
const code = "function helloWorld() { console.log('Hello, world!'); }";
const keywords = ["function", "console", "log"];
console.log(syntaxHighlight(code, keywords));
// Output: function helloWorld() { console.log('Hello, world!'); }
// with keywords wrapped in <span class="keyword"> tags
This function, syntaxHighlight
, highlights keywords in a given code string. It iterates through each character of the code, identifying words and checking if they are keywords. If a word is a keyword, it is wrapped in a <span>
tag with the class “keyword”. The highlighted code is then returned.
6.2 Building a Search Autocomplete Feature
Autocomplete features use character-by-character comparison to suggest relevant search terms as the user types.
function autocompleteSuggestions(input, suggestions) {
const normalizedInput = input.toLowerCase();
return suggestions.filter(suggestion => suggestion.toLowerCase().startsWith(normalizedInput));
}
// Example usage
const input = "app";
const suggestions = ["apple", "application", "apricot", "banana"];
console.log(autocompleteSuggestions(input, suggestions)); // Output: [ 'apple', 'application', 'apricot' ]
This function, autocompleteSuggestions
, provides autocomplete suggestions based on user input. It filters a list of suggestions to include only those that start with the user’s input (case-insensitive). The function returns an array of matching suggestions.
6.3 Analyzing Log Files for Specific Errors
Analyzing log files for specific errors often involves character-by-character comparison to identify relevant log entries.
function findErrorLogs(logData, errorKeywords) {
const errorLogs = [];
const logs = logData.split('n');
for (const log of logs) {
const logLower = log.toLowerCase();
if (errorKeywords.some(keyword => logLower.includes(keyword.toLowerCase()))) {
errorLogs.push(log);
}
}
return errorLogs;
}
// Example usage
const logData = `
2023-07-18 10:00:00 - INFO: Application started
2023-07-18 10:00:01 - ERROR: NullPointerException occurred
2023-07-18 10:00:02 - WARNING: Deprecated function used
2023-07-18 10:00:03 - ERROR: ArrayIndexOutOfBoundsException occurred
`;
const errorKeywords = ["error", "exception"];
console.log(findErrorLogs(logData, errorKeywords));
// Output:
// [
// '2023-07-18 10:00:01 - ERROR: NullPointerException occurred',
// '2023-07-18 10:00:03 - ERROR: ArrayIndexOutOfBoundsException occurred'
// ]
This function, findErrorLogs
, analyzes log data to find log entries that contain specific error keywords. It splits the log data into individual log entries and checks if each entry (case-insensitive) contains any of the specified error keywords. The function returns an array of log entries that contain error keywords.
7. Best Practices for String Comparison in JavaScript
To ensure efficient and accurate string comparisons, follow these best practices:
7.1 Use Strict Equality (===
)
Use the strict equality operator (===
) to compare strings, as it checks both value and type without type coercion.
7.2 Normalize Strings Before Comparison
Normalize strings by converting them to lowercase or uppercase to avoid case-sensitive comparison issues.
7.3 Handle Unicode Characters Correctly
Use codePointAt()
to handle Unicode characters beyond the basic multilingual plane (BMP).
7.4 Consider Performance Implications
Be mindful of performance implications, especially when dealing with large strings or complex comparisons.
7.5 Test Thoroughly
Test your string comparison logic thoroughly with various inputs to ensure accuracy and robustness.
8. Common Mistakes to Avoid
Avoid these common mistakes when comparing strings in JavaScript:
8.1 Using Loose Equality (==
)
Avoid using the loose equality operator (==
), as it can lead to unexpected results due to type coercion.
8.2 Ignoring Case Sensitivity
Ignoring case sensitivity can lead to incorrect comparisons. Always normalize strings or use case-insensitive regular expressions.
8.3 Failing to Handle Unicode Characters
Failing to handle Unicode characters correctly can lead to incorrect comparisons, especially with characters outside the BMP.
8.4 Overlooking Performance Issues
Overlooking performance issues can lead to slow and inefficient code. Be mindful of the performance implications of your string comparison logic.
9. Conclusion: Mastering String Comparison in JavaScript
Mastering character-by-character string comparison in JavaScript is essential for a wide range of programming tasks. By understanding the various methods, advanced techniques, and best practices, you can write efficient and accurate code for validating data, searching for patterns, and implementing complex algorithms. Explore COMPARE.EDU.VN for more insights and resources to enhance your string manipulation skills.
Whether you’re building a code editor, implementing a search autocomplete feature, or analyzing log files, character-by-character string comparison provides the precision and control you need.
10. Call to Action
Ready to take your string comparison skills to the next level? Visit COMPARE.EDU.VN to explore more detailed comparisons, expert reviews, and resources that will help you make informed decisions and optimize your code. Our comprehensive guides and practical examples will empower you to tackle any string manipulation challenge with confidence.
Don’t struggle with complex comparisons alone. Let COMPARE.EDU.VN be your trusted resource for all your comparison needs. Visit us today at 333 Comparison Plaza, Choice City, CA 90210, United States, or contact us via WhatsApp at +1 (626) 555-9090. Start making smarter choices with compare.edu.vn.
Frequently Asked Questions (FAQ)
1. What is the best method for comparing strings character by character in JavaScript?
The best method depends on the specific use case. For simple comparisons, using for
loops or charAt()
is often sufficient. For Unicode support, codePointAt()
is recommended. For more complex comparisons, consider Levenshtein distance or Jaro-Winkler distance.
2. How can I handle case-insensitive string comparisons?
Convert both strings to lowercase or uppercase using toLowerCase()
or toUpperCase()
before comparing them.
3. What is Levenshtein distance, and when should I use it?
Levenshtein distance measures the similarity between two strings by counting the minimum number of single-character edits required to change one string into the other. Use it when you need to find the degree of similarity between two strings, such as in spell checkers or DNA sequencing.
4. How can I use regular expressions for string comparison?
Create a RegExp
object with the desired pattern and use the test()
method to check if a string matches the pattern. Regular expressions are useful for complex pattern matching and validation.
5. What are some common mistakes to avoid when comparing strings in JavaScript?
Avoid using loose equality (==
), ignoring case sensitivity, failing to handle Unicode characters, and overlooking performance issues.
6. How can I optimize loop-based string comparisons?
Use early exit when a mismatch is found, ensure strings are of equal length before starting the comparison, and minimize function calls within the loop.
7. When should I use advanced string comparison techniques like Levenshtein distance or Jaro-Winkler distance?
Use advanced techniques when you need to measure the degree of similarity between two strings, such as in spell checkers, DNA sequencing, or record linkage. These techniques are computationally intensive, so use them only when necessary.
8. Can you provide an example of using character-by-character comparison in a real-world application?
Character-by-character comparison is used in code editors for syntax highlighting, in search engines for autocomplete suggestions, and in log analysis tools for identifying specific errors.
9. How do I compare strings with Unicode characters correctly?
Use the codePointAt()
method to get the Unicode value of each character and compare those values. This ensures that characters outside the basic multilingual plane (BMP) are handled correctly.
10. What is the difference between charAt()
and codePointAt()
?
charAt()
returns a single UTF-16 code unit, while codePointAt()
returns the Unicode code point of the character. codePointAt()
is necessary for handling characters outside the BMP, which are represented by two UTF-16 code units.