# Strings

Strings, as mentioned [before](https://github.com/nushackers/wiki/blob/main/orbital/javascript/datatypes.md) are any ordered set of characters enclosed in quotation marks.

```js
let str = "hello world";
let spaceship = "artemis";
let strongPassword = "c<Db39)(-2?^#_=11MD.{[a"; // not my password
let emoji = "🦾🦵"; // yes this is valid, try it
```

## Indexing

To access a particular character in a string at a particular position, there are 3 ways:

* Square bracket indexes (`[]`)
* The `charAt` method
* The `at` method

{% hint style="info" %}
Strings are 0-indexed, so the first character in a string is considered index 0 and the last character is considered index `str.length - 1`
{% endhint %}

Let's create a string, and use the 3 methods to compare outputs with different cases:

```js
let name = "dino";
```

#### Square brackets

Usage: `str[i]` where `str` is the string and `i` is a nonnegative integer

```js
name[0]; // returns "d"
name[3]; // returns "o"
// Testing with other indices:
name[]; // no input - Uncaught SyntaxError: expected expression, got ']'
name[-2]; // negative number - returns undefined
name[2.7]; // decimal value - returns undefined
name[32]; // index out of range - returns undefined
```

We can see from the above that passing in any value for `i` that is not a nonnegative integer less than the length of the string results in `undefined`.

#### The `charAt` method

Usage: `str.charAt(i)` where `str` is the string `i` is a number

```js
name.charAt(0); // returns "d"
name.charAt(3); // returns "o"
// Testing with other indices:
name.charAt(); // no input - returns "d"
name.charAt(-2); // negative number - returns "d"
name.charAt(2.7); // decimal value - returns "n"
name.charAt(32); // index out of range - returns ""
```

We can see from the above that:

1. passing in a negative value for `i` returns the first character in the string
2. passing in a decimal value for `i` returns the index at position `floor(i)`
3. passing in a value greater than the length for `i` returns an empty string `""`

#### The `at` method

Usage: `str.at(i)` where `str` is the string `i` is a number

```js
name.at(0); // returns "d"
name.at(3); // returns "o"
// Testing with other indices:
name.at(); // no input - returns "d"
name.at(-2); // negative number - returns "n"
name.at(2.7); // decimal value - returns "n"
name.at(32); // index out of range - returns ""
```

We can see from the above that the `at` method behaves similarly to the `charAt` method except for negative indices. In this case, an index of -1 corresponds to the **last** character in a string, and every negative number after that is counting backwards. Thus an index of -2 is the second-to-last character in the string, -3 is the third-to-last character, and so on.

{% hint style="info" %}
Try passing a negative index that is beyond the valid range for negative indices (like `name.at(-10)` for the above example). What happens?
{% endhint %}

## String methods

Strings are provided with a whole host of functions that can operate on strings. These functions are called string methods, and W3Schools has a an [extensive list](https://www.w3schools.com/jsref/jsref_obj_string.asp) of these functions. For now, we'll look at a few in detail, and how they work.

We've already seen 2 string methods that help to get a character in the string at a particular position: `charAt` and `at`.

Let's look at some string formatting methods.

#### Converting cases

To convert a string to all uppercase, we have the `toUpperCase` method. You can probably guess from this that the method to convert a string to all lowercase is `toLowerCase`.

```js
let name = "Dino";
let nameUpper = name.toUpperCase();
let nameLower = name.toLowerCase();
nameUpper; // "DINO"
nameLower; // "dino"
name; // "Dino"
```

Note that the value of `name` has not changed after applying the string methods to it. This is because strings are immutable, so the methods just create new strings.

### Getting subsections

To get a subsection of a string, called a substring, there are a few methods.

```js
let name = "rocket sloth";
```

#### `slice`

The first is the `slice` method. This takes in two arguments, a `start` and `end`, and returns the characters in the string from the `start` index to just before the `end` index:

```js
name.slice(0, 3); // "roc"
name.slice(4, 10); // "et slo"
```

Ommitting the `end` value will return all the characters from the `start` to the end of the string:

```js
name.slice(3); // "ket sloth"
```

If the `end` value is greater than or equal to the `start` value, an empty string is returned:

```js
name.slice(10, 3); // ""
```

If only one argument `k` is passed in, and the argument is negative, then the last `|k|` characters are returned:

```js
name.slice(-5); // "sloth"
```

#### `substr`

The next is the `substr` method. This takes in two arguments, a `start` and `length`, and returns the first `length` characters from the `start` index inclusive.

```js
name.substr(0, 3); // "roc"
name.substr(4, 10); // "et sloth"
```

Ommitting the `length` value will return all the characters from the `start` to the end of the string:

```js
name.substr(3); // "ket sloth"
```

If the `start` is negative, then the characters are counted backwards:

```js
name.substr(-3, 5); // "t slo"
```

#### `substring`

The last method is the `substring` method. This works like the `slice` method but with one change. If `end` is greater than `start`, then the two are swapped:

```js
name.slice(4, 10); // "et slo"
name.substring(4, 10); // "et slo"
name.slice(10, 4); // ""
name.substring(10, 4); // "et slo"
```

### Checking for substrings

There are a few methods to help check if one string is a substring of another. These are `includes`, `startsWith` and `endsWith`. They are case-sensitive and their names are pretty self-explanatory.

```js
let name = "Rocket Sloth";
name.startsWith("Rock"); // true
name.startsWith("rock"); // false
name.endsWith("th"); // true
name.includes(" "); // true
name.includes(""); // true
name.includes("hijse"); // false
```

## String templating

Let's say we want a simple program that will add two numbers and output their sum in the form "x + y = sum".

```js
let x = 10;
let y = 5;
```

### Method 1:

```js
console.log(x, "+", y, "=", (x + y));
```

Passing in multiple arguments `console.log` causes them to be joined into one string with each argument separated by a space. However this method can only be used when a function is able to take in multiple arguments and knows to concatenate them into a string, like `console.log`. The same code will not work with `alert` (see below).

<figure><img src="https://2807223923-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTUqAJOgHs57S8lmqdxRV%2Fuploads%2Fgit-blob-68c7403d3ec7ee033657c0b9a696cd6908f08357%2Fconsole-demo6.gif?alt=media" alt=""><figcaption></figcaption></figure>

### Method 2: String concatenation

```js
console.log(x + " + " + y + " = " + (x + y));
```

As you hopefully recall, the [`+` operator](https://wiki.nushackers.org/orbital/readme-1/operations) when applied to two strings (or to a number and a string) performs string concatenation. This results in a single string being passed in to the function to print out. The advantage of this is that string concatenation results in a string value being formed, so it can be passed in to any function, and can be assigned to a variable/constant as needed. However, if I was not careful and omitted the brackets around `x + y` at the end, I would run into a problem (see below).

<figure><img src="https://2807223923-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTUqAJOgHs57S8lmqdxRV%2Fuploads%2Fgit-blob-0831671b98695cd20c2c276b64f78ce8ee47e4eb%2Fconsole-demo7.png?alt=media" alt=""><figcaption></figcaption></figure>

### Method 3: String templating

This method works similarly to string concatenation, but when substituting multiple values into a string it looks more clean and is easier to read. To form a string template, wrap the string in backticks (\`\`) instead of quotes. Then, at the positions of the variables, use curly braces and the `$` sign before the braces, and place the variable/expression between the braces. See below:

```js
console.log(`${x} + ${y} = ${x + y}`);
```

While this has the same effect as before, it looks a lot cleaner and its clearer to anyone reading the code as to what is going on. There is also less chance of operations getting confused.

<figure><img src="https://2807223923-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTUqAJOgHs57S8lmqdxRV%2Fuploads%2Fgit-blob-3eada803fccd9e05c54bba6e67fd92b9e318cbc7%2Fconsole-demo8.png?alt=media" alt=""><figcaption></figcaption></figure>

## Next steps

Next, we'll look at arrays and some useful array methods.
