Lesson 7: Mastering JavaScript Strings with challenges! (PART - 1)

manoj ymkmanoj ymk
9 min read

πŸ”Ή 1. Summarize the Concept Clearly

What Are Strings?

  • Definition:
    In JavaScript, textual data is stored as strings. There’s no separate "character" type; every character is just a string of length 1.

  • Internal Format:
    All strings use UTF-16 encoding regardless of page encoding.

Types of Quotes

JavaScript supports three ways to delimit strings:

  • Single Quotes:

      let single = 'Hello, world!';
    
  • Double Quotes:

      let double = "Hello, world!";
    
  • Backticks (Template Literals):

      let backticks = `Hello, world!`;
    

Key Benefits of Backticks:

  • Multiline Strings:

      let guestList = `Guests:
      * John
      * Pete
      * Mary`;
    
  • Embedded Expressions:

      function sum(a, b) {
        return a + b;
      }
      alert(`1 + 2 = ${sum(1, 2)}.`); // "1 + 2 = 3."
    

Special Characters and Escaping

  • Newline:

      let str = "Hello\nWorld"; // Inserts a new line
    
  • Escape Character (): Used to include quotes or special characters:

      alert('I\'m the Walrus!');    // Escapes the single quote
      alert("She said, \"Hello!\""); // Escapes the double quotes
      alert(`Backslash: \\`);        // Shows a backslash
    
  • Common Escaped Characters:

    | Escape Sequence | Represents | | --- | --- | | \n | New line | | \r | Carriage return | | \t | Horizontal tab | | \\ | Backslash | | \' / \" | Literal quote |

String Properties and Immutability

  • Length Property:

      let str = "Hello\nWorld";
      alert(str.length); // Counts \n as a single character
    

    Note: Use str.length, not str.length()β€”it’s a property, not a function.

  • Immutability:
    Strings cannot be changed in place. To β€œchange” a string, create a new one.

      let greeting = "Hi";
      greeting = "Hello"; // Creates a new string
    

Accessing and Extracting Characters

  • Accessing Characters:

      let str = "Hello";
      alert(str[0]);   // "H"
      alert(str.at(-1)); // "o" (using .at() for negative indexing)
    

    Note: Square bracket notation does not accept negative indexes.

  • Extracting Substrings:

    • slice(start, end): Supports negative indexes.

        let str = "stringify";
        alert(str.slice(0, 6));  // "string"
        alert(str.slice(-3));    // "ify"
      
    • substring(start, end): Swaps indexes if start > end; negatives are treated as 0.

        alert(str.substring(6, 2)); // "ring" (swaps parameters)
      
    • substr(start, length): (Not part of the core spec; use with caution)

        alert(str.substr(2, 4)); // "ring"
      

Changing String Case

  • Methods:

      alert("Interface".toUpperCase());  // "INTERFACE"
      alert("Interface".toLowerCase());  // "interface"
    

Searching and Comparing Strings

  • Searching:

    • indexOf(substring, start):

        let phrase = "Widget with id";
        alert(phrase.indexOf("Widget")); // 0
        alert(phrase.indexOf("id"));     // 1 (first occurrence)
      
    • includes(substring, start):

        alert(phrase.includes("Widget")); // true
      
    • startsWith()/endsWith():

        alert("Widget".startsWith("Wid")); // true
        alert("Widget".endsWith("get"));   // true
      
  • Comparing Strings:

    • Lexicographic comparison is based on character code values (UTF-16).

    • localeCompare:
      Compares strings according to a locale:

        alert("Γ–sterreich".localeCompare("Zealand")); // -1 (depends on locale)
      
  • Getting Unicode Values:

      alert("Z".codePointAt(0)); // 90
      alert(String.fromCodePoint(90)); // "Z"
    

πŸ”Ή 2. Fill Any Gaps β€” Missing Concepts and Edge Cases

Handling Unicode and Emoji

  • Surrogate Pairs:
    Some characters (like emoji) are represented by two UTF-16 code units.

      let emoji = "😊";
      console.log(emoji.length); // 2 (even though it looks like one character)
      // Use for..of to iterate correctly:
      for (let char of emoji) {
        console.log(char); // "😊" printed once
      }
    

Escaped Sequences in Depth

  • Unicode Escapes:
    Use \u{...} for full Unicode code points.

      alert("\u{1F600}"); // πŸ˜€
    

Tagged Templates (Advanced Concept)

  • Tagged Template Literals:
    A function can process a template literal before it's concatenated.

      function tag(strings, ...values) {
        console.log(strings); // Array of string parts
        console.log(values);  // Array of evaluated expressions
        return "Processed string";
      }
      let result = tag`Hello, ${"world"}!`;
      console.log(result); // "Processed string"
    

String Immutability and Performance

  • Creating New Strings:
    Since strings are immutable, repeated modifications result in new allocations.

    • Use an array and join it for very long strings.
    let parts = [];
    for (let i = 0; i < 100; i++) {
      parts.push("Hello");
    }
    let longString = parts.join(" ");

πŸ”Ή 3. Challenge Me Deeply β€” 10 Coding Challenges + 1 Brain-Twister

🟒 Basic Challenges:

  1. Quote Conversion:
    Write a function that takes a string with single quotes and returns it with double quotes instead.

  2. Escape Characters:
    Create a string that contains newlines, tabs, and quotes correctly escaped.

  3. Substring Extraction:
    Using slice(), write a function that returns the last three characters of any string.

🟑 Intermediate Challenges:

  1. Custom Length Property:
    Simulate the length property by iterating through the string character by character (do not use .length).

  2. Iteration with .at():
    Write a function that, given a string and a negative index, returns the correct character using .at().

  3. Locale-Aware Comparison:
    Write a function that sorts an array of country names using localeCompare().

πŸ”΄ Advanced Challenges:

  1. Tagged Template Parser:
    Create a tagged template function that sums numeric expressions within a template string.

  2. Unicode Surrogate Handling:
    Write a function that correctly counts user-perceived characters (grapheme clusters) in a string containing emoji.

  3. Substring Loop:
    Implement a function that finds and prints all occurrences of a substring within a string without using built-in methods like indexOf().

  4. Immutable Update:
    Create a function that replaces the second character of a string with a different character, without using any built-in string replacement methods.

🎯 Bonus Brain-Twister:

  1. Template vs. String Literals: Without running the code, predict the output of:

    const firstName = "John";
    const lastName = "Doe";
    function tag(strings, ...values) {
      console.log(strings);
      console.log(values);
      return strings[0] + values[0] + strings[1].toUpperCase();
    }
    console.log(tag`Hello, ${firstName} ${lastName}`);
    
    • Consider how tagged templates break down the literal parts and expressions.

πŸ”Ή 4. Interview-Ready Questions

πŸ“˜ Concept-Based:

  • What are the differences between single quotes, double quotes, and backticks in JavaScript?
    β†’ Explain the benefits of template literals (multiline, embedded expressions).

  • How do escape sequences work in strings?
    β†’ Detail how \n, \t, \\, and Unicode escapes are processed.

  • Explain string immutability and its implications in JavaScript.

🧩 Scenario-Based:

  • You need to format user input that might contain multiple lines and special characters. How do you process and display it safely in the browser?

  • How would you extract a substring from a Unicode string containing emoji without breaking characters?

🐞 Debugging-Style:

  • A developer mistakenly calls str.length() instead of str.length and gets an error. Explain why this error occurs.

  • Why might str.substring(6, 2) return the same result as str.substring(2, 6)?

  • If you get unexpected results when comparing strings with diacritical marks, what potential issue should you investigate? (Hint: Think locale.)

βœ… Best Practices:

  • Do:

    • Use backticks for template literals to easily embed expressions and multiline strings.

    • Use slice() for substring extraction (due to its support for negative indices).

    • Use localeCompare() when sorting strings according to user locale.

    • Be mindful of Unicode and surrogate pairs when processing strings.

  • Don’t:

    • Assume .length() is a functionβ€”remember, it’s a property.

    • Modify strings in place since they are immutable; always create new strings.

    • Overuse substr() as it’s considered legacy (Annex B).


πŸ”Ή 5. Real-World Usage

Front-End:

  • Templating:
    Template literals are used extensively in frameworks like React, Vue, and Angular for JSX/templating.

  • User Input Processing:
    Escaping user input for display in HTML to prevent XSS attacks.

  • Internationalization (i18n):
    Using methods like localeCompare() and Unicode handling for multilingual support.

Back-End:

  • String Processing:
    Server-side code (Node.js) uses strings for file I/O, logging, and constructing dynamic SQL queries.

  • Data Parsing:
    Parsing CSV files, logs, or data streams that use string manipulation functions (split(), trim(), etc.).

Libraries & Frameworks:

  • Lodash or Underscore: Provide utilities for safe string manipulation.

  • Intl API: Offers advanced localization and formatting for strings and numbers.


πŸ”Ή 6. Remember Like a Pro

Mnemonics & Analogies:

  • Quotes:
    Think β€œSingle, Double, Backtick – choose your ticket” to remember that backticks are the versatile, modern choice.

  • Escape Characters:
    β€œEvery Special Character Starts with a Backslash” reminds you that \n, \t, etc., all begin with \.

  • Immutability:
    Imagine a string as a printed page – you can’t erase a letter; you must print a whole new page if you need a change.

Visual Cheatsheet (Text-Based Mind Map):

Strings
β”œβ”€β”€ Definition: Textual data (UTF-16)
β”œβ”€β”€ Quotes:
β”‚   β”œβ”€β”€ Single: 'Hello'
β”‚   β”œβ”€β”€ Double: "Hello"
β”‚   └── Backticks: `Hello ${name}`
β”œβ”€β”€ Special Characters:
β”‚   └── Escapes: \n, \t, \\, \u, etc.
β”œβ”€β”€ Properties:
β”‚   β”œβ”€β”€ length (no parentheses)
β”‚   └── Immutable
β”œβ”€β”€ Access Methods:
β”‚   β”œβ”€β”€ [index]
β”‚   └── .at(index)
β”œβ”€β”€ Substring Extraction:
β”‚   β”œβ”€β”€ slice(start, end)
β”‚   β”œβ”€β”€ substring(start, end)
β”‚   └── substr(start, length)
β”œβ”€β”€ Case Changing:
β”‚   β”œβ”€β”€ toLowerCase()
β”‚   └── toUpperCase()
β”œβ”€β”€ Searching:
β”‚   β”œβ”€β”€ indexOf(), lastIndexOf()
β”‚   β”œβ”€β”€ includes(), startsWith(), endsWith()
β”‚   └── localeCompare() for i18n
└── Additional:
    β”œβ”€β”€ trim(), repeat()
    └── Tagged Templates

πŸ”Ή 7. Apply It in a Fun Way β€” Mini Project

Mini Project: Multi-language Guest Book

Goal: Build a small web app that:

  • Accepts user input for a guest name and message.

  • Displays the guest book with each entry formatted on multiple lines using template literals.

  • Supports search functionality for entries (case-insensitive, locale-aware).

  • Utilizes proper escaping and trimming for user input.

Steps:

  1. Create an HTML Form:

    • Input fields for Name and Message.

    • A submit button.

  2. Capture Input and Sanitize:

    • Trim whitespace using str.trim().

    • Escape any HTML to avoid XSS (e.g., replace < with &lt;).

  3. Format Entry:

    • Use template literals for multiline formatting:

        const entry = `Guest: ${name}
        Message: ${message}`;
      
  4. Store and Display:

    • Append the new entry to an array.

    • Display all entries in a <div> with each entry separated by a horizontal line.

  5. Search Functionality:

    • Add an input field to search the guest book.

    • Use String.prototype.includes() (or localeCompare() for advanced sorting) to filter entries, ignoring case.

  6. Enhance with Localization:

    • Use localeCompare() when sorting or filtering entries to support multiple languages.
  7. Deploy & Test:

    • Ensure proper functioning across browsers.

    • Check for correct handling of multiline and special characters.

Extension Bonus:

  • Implement a feature that saves entries to localStorage so that the guest book persists on refresh.

  • Allow exporting the guest book as a JSON file, converting strings properly.


πŸ”Ή Bonus: Extra Considerations

Common Mistakes:

  • Treating .length as a function.

  • Forgetting to escape quotes in strings.

  • Misusing substring methods (confusing slice() with substr()).

  • Not considering Unicode surrogate pairs in emoji.

Performance Tips:

  • For heavy string manipulation, consider building arrays and using join() to improve performance.

  • Use the built-in Intl API for locale-sensitive string operations.

Polyfills / Alternatives:

  • For environments lacking modern String methods (like .at()), consider polyfills from the core-js library.
0
Subscribe to my newsletter

Read articles from manoj ymk directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

manoj ymk
manoj ymk