How to avoid magic numbers when manipulating strings

String functions like substr, substring, or slice all take character indices as parameters.

For example, slice returns the characters from the from index to the to index you pass in. Or, if no to index is passed in, it returns all remaining characters starting from the from index.

"Hello World".slice(0, 5)
// "Hello"
"Hello World".slice(6)
// "World"

But, when written this way, it's not always clear what the numbers mean, especially since you'll normally call slice on a variable instead of a string literal. Like this:

// "World"    

To avoid that, instead of using a number, try to communicate what the number means. For example, to find out who the greeting is saying "Hello" to:

greeting.slice("Hello ".length)
// "World"

By representing the character index as the length of the string before "World" we avoid confusion about why index 6 was chosen.

If our app changes from "Hello " to "Hi ", instead of changing an index from 6 to 3, we can simply edit the string.

While theoretically slower, in practice the extra time spent on the length property lookup is so insignificant that it's not worth sacrificing readability for.

Let's look at a few more examples.

"Hello World!".slice("Hello ".length, -"!".length)
// "World"

Here the thing we're greeting is wrapped between the "Hello " and the exclamation mark, so we use both strings to get the correct indices.

Note the minus sign before the "!". A negative index for the to parameter tells the slice function to start counting backward from the end of the string.

str = "It's July 20, 2088. Hello World! How are things?"

Given this string, how can we figure out who's being greeted? The exact indices we need to use change depending on the date.

We can use the indexOf function to find the correct character indices to use for the slice call.

str.slice(str.indexOf("Hello "), str.indexOf("!"))
// "Hello World"

Now, all we need to do is move the from after the "Hello ":

str.slice(str.indexOf("Hello ") + "Hello ".length, str.indexOf("!"))