【JavaScript】''とか""とか``って何が違うの？

JavaScriptの`''`、`""`、```` `` ````は、どれも**文字列を示す記号**です。
この記事ではこれらの違い、そしてテンプレートリテラルについて紹介します。

# `''`と`""`
`''`と`""`は**全く同じ**です。
記号が違うだけで、どちらも同じ文字列になります。

もちろん、`===`で比較してみても`true`になります。
```js
// trueになる
'Hello World!' === "Hello World!"
```

# バッククォテーション（``）
```` `` ````を使うと、テンプレートリテラルという機能を使うことができます。

テンプレートリテラルでは、```` `` ````で囲った文字列の中に`${}`を使うことで値を埋め込めます。
構文は大体こんな感じです。

```js
console.log(`計算結果: ${10 + 20}`) // 10 + 20を埋め込む
// 計算結果: 30
```


## 例

例えば、以下のように`a`と`b`の2つの変数があります。
```js
const a = 10
const b = 20
```

ここでは、`a + b`の計算結果である`30`を、`a + b = 30です`というフォーマットで出力してみます。

### `+`で繋げた場合
まずは比較用に、`+`で数値と文字列を繋げた例を紹介します。

```js
console.log("a + b = " + (a + b) + "です")
```

:::note warn
`(a + b)`の`()`を省くと出力結果が変わってしまいます。
:::

このコードでは`+`を2つの目的で使用しています。

- 文字列と数値を繋げて文字列にする
- 数値と数値を足し算する

そのため、`+`が**何の役割を果たすのかわかりづらく**なってしまっています。
これは主観ですが、このようなコードは少し読みづらいです。

### テンプレートリテラルを使う場合
先ほどのコードは、テンプレートリテラルを使うと以下のように書けます。

```js
console.log(`a + b = ${a + b}です`)
```

どうでしょうか。読みやすいと思いませんか？
もし今思わなくても、慣れてきたらこちらのほうが読みやすいと感じるはずです。たぶん。

:::note
先ほどのコードもこのコードも、**実行結果は全く同じ**です。
そのため好きなほうを使えばいいのですが、**どうせ使うなら読みやすいほうを使いたくないですか？**
:::

この記法を使うと、以下のようにコードが読みやすくなります。

- `+`がコードから消えるので、この`+`の役割は何？を考える必要がなくなる
    - 代わりの`${}`は、少なくとも`$`がコードに出てくる機会はほぼない
- ハイライトがわかりやすく、どの部分が文字列でないのか直感的にわかる

## それ以外の特徴
```` `` ````で囲った文字列は、`''`や`""`と比べてほかにも以下の特徴があります。

- 複数行の文字列が書ける
- タグ付きテンプレートという構文が使える

詳細は[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Template_literals#文字列の補間)をご覧ください。

# JavaScriptの文字列
ということで、ここからはJavaScriptの文字列について解説していきます。

前提として、文字列は`''`、`""`、```` `` ````で囲むことで作成できます。
文字列は`console.log`でログに出力したり、変数に代入したりできます。

また、文字列は`string`型と呼ばれることもあります。

## プリミティブ
JavaScriptの文字列は[プリミティブ](https://developer.mozilla.org/ja/docs/Glossary/Primitive)です。
プリミティブはオブジェクトでない値のことで、**文字列や数値、真偽値**などがあります。

プリミティブには以下のような仕様があります。

- メソッドはないが呼び出せる
- 不変（イミュータブル）

詳細は[MDN](https://developer.mozilla.org/ja/docs/Glossary/Primitive)をご覧ください。

## 値で比較される

`===`演算子を使った比較では、文字列の参照ではなく値が同じかどうかで比較されます。

```js
"abc" === "abc" // true
```

### 参照とは

反対に、オブジェクトは参照で比較されます。
ここでオブジェクトと呼ばれるものは、例えばこんなものがあります。

- 配列
- オブジェクトリテラル（`{}`を使って作ったオブジェクト）
- `Map`や`Set`など

:::note warn
参照とは何かを正確に説明する能力は筆者にはないので、ざっくりとした解説になります。
:::

参照とは簡単に言うと、**値の場所を保持しておく値**のようなものです。
参照はオブジェクトごとに一意です。

:::note
追記 2024/12/4 

[ECMAScriptの仕様書](https://tc39.es/ecma262/multipage/notational-conventions.html#sec-identity)を読んでみたところ、比較はおよそこのような感じになっていそうでした。

- [identity](https://tc39.es/ecma262/multipage/notational-conventions.html#sec-identity)というものがある
- identityがない値（*Values without identity*）がある
    - number / bigInt / string / null / undefined / boolean
    - これらはidentityで比較されないが、比較の際に参照を使う（[ここ](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#prod-gVfoAVuz)の`Let lRef be ? Evaluation of EqualityExpression.`のあたり）
- identityを持つ値（*value with identity*）がある
    - Object / Symbol（例外: `Symbol.for`）
    - これらはidentityで比較される

@juner ありがとうございました！
:::

普通にJavaScriptを書いている限り、参照の実態を直接見る機会はありません。

配列やオブジェクトリテラルは**参照で比較されます。**
参照はオブジェクトごとに一意なので、中身が同じでも参照が異なれば`false`を返します。

```js
const array1 = [1, 3, 5]
const array2 = [1, 3, 5]

array1 === array2 // false
```

## メソッドが呼び出せる

文字列はメソッドが呼び出せます。

メソッドには様々なものがあり、例えば文字列の中に別の文字列が含まれるかどうかを返す`includes`があります。

```js
const str = 'Hello World!'
console.log(str.includes('Hello')) // true
console.log(str.includes('Hi!')) // false
```

全てのメソッドは[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/includes)から見ることができます。
暇なときにでも眺めてみると、どんなメソッドがあるかが知れておすすめです。

:::note
実は、**プリミティブにメソッドはありません。**
ではなぜ上でメソッドが呼び出せたかというと、自動でラッパーオブジェクトが作られるからです。

例えば文字列のラッパーオブジェクトは`String`オブジェクトです。
文字列のメソッドを呼び出そうとすると、文字列プリミティブは自動で`String`オブジェクトに変換されます。
そして、そのラッパーオブジェクトに対してメソッドが呼び出されます。

なお、普通にJavaScriptコードを書いている限りは、この仕様を知らなくても大丈夫だと思います。
:::