Start learning free

LESSON 63 OF 410 · STRINGS I

String Immutability in JavaScript: Why Strings Can't Be Changed

Lesson Read the full explanation

In JavaScript, strings are immutable, which means that they cannot be altered once created.

For example, the following code:

let message = "Jello world";

message[0] = 'H';

console.log(message);

would output:

Jello world

As you can see, the program executes but the string wasn't changed after all. Some languages like Python wouldn't even let this code run, but throw a TypeError. JavaScript is more permissive, which is not necessary a good thing.

As a programmer, I'd rather be told when I made a mistake early on so I can fix it, instead of running into problems later on and not knowing what the root of those problems is.


Variable can still be changed:

Note that this does not mean that message cannot be changed, just that the individual characters of a string literal cannot be changed.

"Jello world" is a string literal that JavaScript stores in memory, while message is a variable that refers to that string literal.

When we do message[0] = 'H', we are trying to alter the string literal "Jello world", which is not allowed.

But like any other variable, message can be changed by reassigning it with a new string, like this:

let message = "Jello world";

message = "Hello world";

console.log(message);

This code would output:

Hello world

Instead of trying to alter the first string, this code now creates a new one ("Hello world"), stores it in memory and tells message to refer to this new string.


Assignment
Follow the Coding Tutorial and let's practice with string immutability!


Hint
Look at the examples above if you get stuck.


STEP 1 OF 1
    Ctrl + Enter to check

    JAVASCRIPT · STRINGS I

    String Immutability in JavaScript, explained

    What immutable means

    Strings in JavaScript are immutable: once a string exists, none of its characters can be changed, added or removed. Every operation that looks like it edits a string actually builds a new one and leaves the original alone.

    Trying to change a character in place shows this:

    let message = "Jello world";
    
    message[0] = 'H';
    
    console.log(message);   // Jello world
    

    The assignment has no effect. What happens next depends on the mode the code runs in. In ordinary ("sloppy") scripts the failed assignment is ignored silently, as above. In strict mode, which is always on inside ES modules and class bodies, and which a "use strict" line at the top of a file switches on, the same line throws:

    TypeError: Cannot assign to read only property '0' of string 'Jello world'
    

    Either way, the string is still "Jello world" afterwards. The same applies to message.length = 3 and to adding a property such as message.foo = 1.

    The variable can still change

    Immutable does not mean that the variable is fixed. A variable declared with let can be pointed at a different string at any time:

    let message = "Jello world";
    message = "Hello world";
    console.log(message);   // Hello world
    

    This does not alter the old string. It creates a second string, "Hello world", and makes message refer to it. The old string is simply no longer used, and JavaScript cleans it up when nothing refers to it. It is the same way a number works: let n = 1; n = 2; does not turn the value 1 into 2, but makes n hold a different value.

    Do not confuse this with const. A const variable cannot be reassigned at all, so const c = "hi"; c = "yo"; throws TypeError: Assignment to constant variable. That is about the variable. Immutability is about the string value, and it holds for let and const alike.

    Methods return new strings

    Every string method leaves the original untouched and returns a new string. The result is lost unless you store it:

    const word = "bndrei";
    word.toUpperCase();              // the result is thrown away
    console.log(word);               // bndrei
    
    const loud = word.toUpperCase();
    console.log(loud);               // BNDREI
    console.log(word);               // bndrei
    

    Joining works the same way. name += "!" builds a new string and stores it in name. Another variable that held the old string keeps its old value:

    let a = "hi";
    let b = a;
    b += "!";
    console.log(a, b);   // hi hi!
    

    Replacing a character: the exercise

    Someone saved a name with a typo: name holds "bndrei Chiriac" instead of "Andrei Chiriac". Their fix, name[0] = 'A';, tries to change the first character in place, which a string does not allow. The fix is to build a new string and store it in the variable:

    1. Take everything except the first character. name.substr(1) returns the text starting at index 1, which is "ndrei Chiriac". (slice(1) does the same and is the modern choice, because substr is a legacy method.)
    2. Put the correct first letter in front. 'A' + name.substr(1) joins the two pieces into "Andrei Chiriac".
    3. Assign the new string back to name. This is a reassignment, which is allowed.
    let name = "bndrei Chiriac";
    
    // Change code below:
    
    name = 'A' + name.substr(1);
    

    These versions give the same result: 'A' + name.slice(1), `A${name.slice(1)}` and name.replace("b", "A"). The last one replaces the first match of "b", which is the first letter here.

    Changing one character in general

    To change the character at index i, join the part before it, the new character and the part after it:

    const s = "Jello";
    const i = 0;
    const fixed = s.slice(0, i) + "H" + s.slice(i + 1);
    console.log(fixed);   // Hello
    

    When you need to change many characters, turn the string into an array, edit the array and join it back, because arrays are mutable:

    const chars = [..."hello"];
    chars[0] = "J";
    console.log(chars.join(""));   // Jello
    

    Why strings are immutable

    Immutable strings are safe to share. Two variables can refer to the same text without one of them changing it behind the other's back. They also work as keys in objects and maps, because a key's value can never change after it is stored. A cost is that building a long string by repeating += creates many short-lived strings, although JavaScript engines optimize this well. For very large amounts of text, collecting pieces in an array and calling join("") once is a common alternative.

    Common mistakes

    • Assigning to an index. s[0] = 'x' never changes the string. It is ignored in sloppy mode and throws a TypeError in strict mode.
    • Calling a method and ignoring the result. s.trim(), s.replace(...) and s.toUpperCase() do not change s. Write s = s.trim() if you want the new value kept.
    • Thinking const is what makes strings immutable. A let string is just as unchangeable. let only allows the variable to point at another string.

    Key takeaways

    • You cannot change a character of a string in place. Reading s[i] works, and writing to it does not.
    • Reassigning a let variable to a new string is fine.
    • String methods and + return new strings, so store the result.
    • To "edit" a string, build a new one with slice and +, or go through an array of characters.
    Keep going with JavaScriptAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free