Skip to the content.

Strings

Click ★ if you like the project. Your contributions are heartily ♡ welcome.



Definition

Quotes

  1. Strings can be enclosed within either single quotes, double quotes or backticks:
    1. let singleQuote = 'single quoted';
      let doubleQuote = "double quoted";
      let backtick = `backticks`;
      
      function sum(a, b) {
        return a + b;
      }
      
      alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.
      
  2. Backticks also allow us to specify a template function before the first backtick.
  3. The syntax is: func `string`;
    1. Follow to this Template literals for more details.

Special characters

1. create multiline strings

let guestList = "Guests:\n * John\n * Pete\n * Mary";

alert(guestList); // a multiline list of guests, same as above
Character Description
\n New line
\r In Windows text files a combination of two characters \r\n represents a new break,
while on non-Windows OS it’s just \n.
That’s for historical reasons, most Windows software also understands \n.
\’, \", `\` Quotes
\\ Backslash
\t Tab
\b, \f, \v Backspace, Form Feed, Vertical Tab – mentioned for completeness, coming from old times,
not used nowadays (you can forget them right now).

String Length

Accessing characters

let str = `Hello`;

// the first character
alert( str[0] ); // H
alert( str.at(0) ); // H


// the last character
alert( str[str.length - 1] ); // o
alert( str.at(-1) ); // o 
alert( str[-1] ); // undefined 

Iterate

for (let char of "Hello") {
  alert(char); // H,e,l,l,o (char becomes "H", then "e", then "l" etc)
}

Strings are Immutable

let str = 'Hi';

str[0] = 'h'; // error
alert( str[0] ); // (doesn't work) TypeError: Cannot assign to read only property '0' of string 'Hi'

str = 'h' + str[1]; // replace the string

alert( str ); // hi
alert( 'Interface'.toUpperCase() ); // INTERFACE
alert( 'Interface'.toLowerCase() ); // interface
alert( 'Interface'[0].toLowerCase() ); // 'i'

Searching for a substring

1. str.indexOf(‘string’)

  1. It looks for the substr in str, starting from the given position pos, and returns the position where the match was found or -1 if nothing can be found.
let str = 'Widget with id';

alert( str.indexOf('Widget') ); // 0, because 'Widget' is found at the beginning
alert( str.indexOf('widget') ); // -1, not found, the search is case-sensitive

alert( str.indexOf("id") ); // 1, "id" is found at the position 1 (..idget with id)
  1. The optional second parameter allows us to start searching from a given position.
let str = 'Widget with id';
alert( str.indexOf('id', 2) ) // 12

// WORD SEARCH ALGORITHM
let str = 'As sly as a fox, as strong as an ox';

let target = 'as'; // let's look for it

let pos = 0;
while (true) {
  let foundPos = str.indexOf(target, pos);
  if (foundPos == -1) break;

  alert( `Found at ${foundPos}` ); // 7 17 27 
  pos = foundPos + 1; // continue the search from the next position
}

// SHORT HAND 
let str = "As sly as a fox, as strong as an ox";
let target = "as";

let pos = -1;
while ((pos = str.indexOf(target, pos + 1)) != -1) {
  alert( pos );
}
  1. Return value when using an empty search string
"hello world".indexOf(""); // returns 0
"hello world".indexOf("", 0); // returns 0
"hello world".indexOf("", 3); // returns 3

// pos > str.length, then returns str.length
"hello world".indexOf("", 11); // returns 11
"hello world".indexOf("", 13); // returns 11

2. str.lastIndexOf(substr, position)

let str = 'As sly as a fox, as strong as an ox';

let target = 'as'; // let's look for it

let pos = str.length; // last index
while (true) {
  let foundPos = str.indexOf(target, pos);
  if (foundPos == -1) break;

  alert( `Found at ${foundPos}` ); // 27 17 7
  pos = foundPos - 1; // continue the search from the previous position
}

let str = "Hello World, Hello!";
let lastIndex = str.lastIndexOf("Hello");  // Result: 13
let emptyIndex = str.lastIndexOf("");      // Result: 26 (length of the string)

3. str.includes(‘string’):

alert( "Widget with id".includes("Widget") ); // true

alert('World'.includes("world"));   // Result: false (case-sensitive)
alert( "Hello".includes("Bye") ); // false
alert( "Widget".includes("id", 3) ); // false, from position 3 there is no "id"

4. str.startsWith(‘st’):

  1. alert( "Widget".startsWith("Wid") ); // true, "Widget" starts with "Wid"

    5. str.endsWith(‘ng’):

  2. alert( "Widget".endsWith("get") ); // true, "Widget" ends with "get"

Getting a substring

method selects… negatives
slice(start, end) from start to end (not including end) allows negatives
substring(start, end) between start and end (not including end) negative values mean 0
substr(start, length) from start get length characters allows negative start

1. str.slice:

  1. Returns the part of the string from start to (but not including) end.
  2. Negative values for start/end are also possible.
    1.  let str = "stringify";
       alert( str.slice(0, 5) ); // 'strin', the substring from 0 to 5 (not including 5)
       alert( str.slice(0, 1) ); // 's', from 0 to 1, but not including 1, so only character at 0
      
       // If there is no second argument, then slice goes till the end of the string:
       alert( str.slice(2) ); // 'ringify', from the 2nd position till the end
      
       // NEGATIVE
       // start at the 4th position from the right, end at the 1st from the right
       alert( str.slice(-4, -1) ); // 'gif'
      

2. str.substring:

  1. Returns the part of the string between start and end (not including end).
  2. Negative arguments are (unlike slice) not supported, they are treated as 0.
  3. This is almost the same as slice, but it allows start to be greater than end (in this case it simply swaps start and end values).
    1.  let str = "stringify";
      
       // these are same for substring
       alert( str.substring(2, 6) ); // "ring"
       alert( str.substring(6, 2) ); // "ring"  (IT SWAPS THE VALUES)
      
       // ...but not for slice:
       alert( str.slice(2, 6) ); // "ring" (the same)
       alert( str.slice(6, 2) ); // "" (an empty string)
      

3. str.substr:

  1. Returns the part of the string from start, with the given length.
  2. this one allows us to specify the length instead of the ending position:
  3. it’s not recommended to use it. In practice, it’s supported everywhere. (in future DEPRECATED)
    1.  let str = "stringify";
       alert( str.substr(2, 4) ); // 'ring', from the 2nd position get 4 characters
      
       // The first argument may be negative, to count from the end:
       alert( str.substr(-4, 2) ); // 'gi', from the 4th position get 2 characters
      

Comparing strings

  1. A lowercase letter is always greater than the uppercase:
    1. alert( 'a' > 'Z' ); // true
      
  2. Letters with diacritical marks are “out of order”:
    1. alert( 'Österreich' > 'Zealand' ); // true
      

str.codePointAt(pos)

alert( String.fromCodePoint(90) ); // Z
alert( String.fromCodePoint(65) ); // A
alert( String.fromCodePoint(0x5a) ); // Z (we can also use a hex value as an argument)

let str = '';

for (let i = 65; i <= 220; i++) {
  str += String.fromCodePoint(i);
}
alert( str );
// Output:
// ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„
// ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜ

Tasks

Uppercase the first character

ucFirst("john") ==> "John";
SHOW SOLUTION ```js function ucFirst(str) { if (!str) return str; return str[0].toUpperCase() + str.slice(1); } alert( ucFirst("john") ); // John ```

Check for spam

checkSpam('buy ViAgRA now') == true
checkSpam('free xxxxx') == true
checkSpam("innocent rabbit") == false
SHOW SOLUTION ```js function checkSpam(str) { let lowerStr = str.toLowerCase(); return lowerStr.includes('viagra') || lowerStr.includes('xxx'); } alert( checkSpam('buy ViAgRA now') ); alert( checkSpam('free xxxxx') ); alert( checkSpam("innocent rabbit") ); ```

Truncate the text

truncate("What I'd like to tell on this topic is:", 20) == "What I'd like to te…"

truncate("Hi everyone!", 20) == "Hi everyone!"
SHOW SOLUTION ```js function truncate(str, maxlength) { return (str.length > maxlength) ? str.slice(0, maxlength - 1) + '…' : str; } ```

Extract the money

alert( extractCurrencyValue('$120') === 120 ); // true
SHOW SOLUTION ```js function extractCurrencyValue(str) { return +str.slice(1); } ```

String Methods

str.at()

str.charAt()

codePointAt()

code point = U+00F1 or "\u00F1"

FUN: You can use this code in HTML as an entity without icon, &#128525.

concat()

endWith()

match()

If you only want the first match found, you might want to use RegExp.prototype.exec() instead.

let str = "The rain in Spain stays mainly in the plain";
let result1 = str.match(/ain/g);  // Result: ["ain", "ain", "ain"]
let result2 = str.match(/xyz/);   // Result: null (no match found)
let result2 = str.match(/ain/);   // Result: ["ain"]

const str1 = "NaN means not a number. Infinity contains -Infinity and +Infinity in JavaScript.";
str1.match("number"); // "number" is a string. returns ["number"]

console.log("123".match("1.3")); // [ "123" ]
console.log("123".match("1\\.3")); // null

normalize()

let str = "e\u0301";  // 'é' as 'e' + combining accent
let normalized = str.normalize();  // Result: "é" (as a single composed character)

In this example, the normalize() method converts the decomposed form (e + accent) into the composed form (é).

padEnd()

let str = "Hello";
let result1 = str.padEnd(10);         // Result: "Hello     " (adds 5 spaces)
let result2 = str.padEnd(10, ".");    // Result: "Hello....." (adds 5 dots)
let result3 = str.padEnd(8, "123");   // Result: "Hello123" (pads with "123")

padStart()

let str = "Hello";
let result1 = str.padStart(10);         // Result: "     Hello" (adds 5 spaces)
let result2 = str.padStart(10, ".");    // Result: ".....Hello" (adds 5 dots)
let result3 = str.padStart(8, "123");   // Result: "123Hello" (pads with "123")

repeat()

let str = "Hello";
let result1 = str.repeat(3);   // Result: "HelloHelloHello"
let result2 = str.repeat(0);   // Result: "" (empty string)
let result2 = str.repeat(-1); // RangeError
let result2 = str.repeat(1 / 0); // RangeError

replace()

let str = "Hello World";
let result1 = str.replace("World", "JavaScript");  // Result: "Hello JavaScript"
let result2 = str.replace(/o/g, "0");              // Result: "Hell0 W0rld" (global replacement)

replaceAll()

let str = "Hello World, Hello Universe";
let result1 = str.replaceAll("Hello", "Hi");    // Result: "Hi World, Hi Universe"
let result2 = str.replaceAll("o", "0");         // Result: "Hell0 W0rld, Hell0 Universe"

If you need the content of the matched text, use String.prototype.match()

let str = "The rain in Spain";
let result1 = str.search(/ain/);   // Result: 5 (first occurrence of "ain")
let result2 = str.search(/xyz/);   // Result: -1 (no match found)

split()

let str = "apple,banana,orange";
let result1 = str.split(",");        // Result: ["apple", "banana", "orange"]
let result2 = str.split(",", 2);     // Result: ["apple", "banana"] (limit to 2 splits)
let result2 = str.split(",", 0);     // Result: [] (empty array, limit to 0 splits)
let result3 = str.split("");         // Result: ["a", "p", "p", "l", "e", ",", ...] (splits every character)

Warning: When the empty string ("") is used as a separator, the string is not split by user-perceived characters (grapheme clusters) or unicode characters (code points), but by UTF-16 code units. This destroys surrogate pairs. See this StackOverflow question

If separator is a regexp that matches empty strings, whether the match is split by UTF-16 code units or Unicode code points depends on if the regex is Unicode-aware.

"😄😄".split(/(?:)/); // [ "\ud83d", "\ude04", "\ud83d", "\ude04" ]
"😄😄".split(/(?:)/u); // [ "😄", "😄" ]

Symbol.iterator

let str = "Hello";
let iterator = str[Symbol.iterator]();  // Creates an iterator for the string

console.log(iterator.next());  // { value: 'H', done: false }
console.log(iterator.next());  // { value: 'e', done: false }
console.log(iterator.next());  // { value: 'l', done: false }
console.log(iterator.next());  // { value: 'l', done: false }
console.log(iterator.next());  // { value: 'o', done: false }
console.log(iterator.next());  // { value: undefined, done: true } (iteration is complete)

toLocaleLowerCase()

let str = "HELLO WORLD";
let result = str.toLocaleLowerCase();  // Result: "hello world"

trim()

let str = "   Hello World   ";
let result = str.trim();  // Result: "Hello World" (whitespace removed from both ends)

1. trimEnd()

let str = "   Hello World   ";
let result = str.trimEnd();  // Result: "   Hello World" (whitespace removed from the end)

2. trimStart()

let str = "   Hello World   ";
let result = str.trimStart();  // Result: "Hello World   " (whitespace removed from the start)

toString()

  1. Number:
    let num = 123;
    let result = num.toString();  // Result: "123" (number converted to string)
    
  2. Array:
    let arr = [1, 2, 3];
    let result = arr.toString();  // Result: "1,2,3" (array elements converted to a comma-separated string)
    
  3. Object: By default, when toString() is called on a regular object, it returns the string "[object Object]". You can override this behavior by defining your own toString() method inside the object.
let obj = {
  name: "John",
  age: 30,
  toString: function() {
    return `Name: ${this.name}, Age: ${this.age}`;
  }
};

let result = obj.toString();  // Result: "Name: John, Age: 30" (custom string representation)

valueOf()

PENDING

String Property

length

console.log(${str} ${str.length}); // Expected output: “Life, the universe and everything. Answer: ```

Source