---
# System prepended metadata

title: 変数と宣言

---

# 変数と宣言

プログラミング言語にはデータに名前をつけて繰り返し利用できるように**変数**という機能が存在する

変数はデータを格納するときに変数の宣言が必要でjsではconst、let、varの３つが存在する。


## const[ES2015]
constは<span style="color: red; ">再代入できない</span>変数の宣言をするときに使う。
```javascript!
const 変数 = 初期値
```

使い方
```javascript!
const bookTitle = 'javaScript Primer'
```
一度に複数定義することが可能
```javascript!
const bookTitle = 'javaScript Primer',
bookCategory = 'プログラミング'
```

```javascript!
const bookTitle = "JavaScript Primer";
const bookCategory = "プログラミング";
```

constで再宣言、再代入することができない
```javascript!
const bookTitle = 'javaScript Primer'
bookTitle = '新しいタイトル' //=> TypeError: invalid assignment to const 'bookTitle'
```

**constを使うとき**
再代入をしてしまい、バグの温床になりかねないので
変数に対して再代入をする必要がないとき、constを使用する

## let[ES2015]
letは<span style="color: red; ">再代入できる</span>変数の宣言をするときに使う。

```javascript!
let 変数 = 初期値
```

使い方
```javascript!
let bookTitle = 'javaScript Primer'
```
letで再宣言はできないが、再代入することはできる
```javascript!
const bookTitle = 'javaScript Primer'
bookTitle = '新しいタイトル' //=> TypeError: invalid assignment to const 'bookTitle'
```
letは初期値を設定しない変数も定義することができる、定義していない場合変数の中身は**undefined**が渡ってくる。
constの場合は初期値は必ず<span style="color: red; ">設定しないといけない</span>
```javascript!
let bookTitle;
// `bookTitle`は自動的に`undefined`という値になる
```

**letを使うとき**
ループなどの反復処理の途中で特定の変数が参照する値を変化させる時はletを使う

## var
let、constが登場する前によく使われていた変数の宣言

varの問題点
### 再定義できる
letやconstは再定義してしまうと構文エラー（SyntaxError)が発生するがvarは再定義できるので思わぬ値の上書きができてしまう
```javascript!
// "x"という変数を定義する
var x = 1;
// 同じ変数名の変数"x"を定義できる
var x = 2;
// 変数xは2となる// "x"という変数を定義する
```

### 変数の巻き上げが起こる

[巻き上げについて](https://itsakura.com/javascript-hoisting)

変数の巻き上げが起こるとき
```javascript!
var a = "123"; //グローバル変数

function fn() {
  console.log(a); // undefined
  var a = '789'
}

fn();
```
変数の巻き上げが起こると...↓
```javascript!
var a = "123"; 

function fn() {
  var a
  console.log(a);
  a = "789"; //ローカル変数
    
fn();
```

変数の宣言が先頭に移動したように見えるので巻き上げと呼ばれる
巻き上げの対策として、ローカル変数を定義するときはlet or constを使用する。

### varはブロックスコープを持たない
ブロックスコープとは{}ごとに囲まれた範囲のこと
ブロック内でletやconstで宣言された変数はブロックスコープを作り外から呼び出されないようにアクセスの制限をしている。

一方でvarはブロックスコープを持たない為外からのアクセスを許可してしまう。
```javascript!
{
  const num1 = 2;
  let num2 = 2;
  var num3 = 3;
}

console.log(num1);ReferenceError: num1 is not defined
console.log(num2);ReferenceError: num2 is not defined
console.log(num3);3

```

varは便利そうに見えるけどどこからでもアクセスできてしまう為意図せずに値を変更してしまう恐れがある為注意が必要



```javascript!
function scope() {
 　let a = 1;
 　const b = 10;
 　var c = 100;

 　console.log(a); 
 　console.log(b); 
 　console.log(c); 
} 

scope(); //エラーは起きない

console.log(a); //ReferenceError: a is not defined
console.log(b); //ReferenceError: b is not defined
console.log(c); //ReferenceError: c is not defined
```
関数スコープはconst,let,varいずれも関数内で宣言された変数は、関数スコープの外からアクセスできない。

**let、 const、 varの特徴**
|  |　let　| const | var |
| -------- | -------- | -------- | -------- | 
| 再代入　| ○　|　　✖︎　| ○　|
| 再宣言　|　✖︎　|　✖︎　|　○　|
| ブロックスコープ　|　○　|　○　|　✖︎　|
| 関数スコープ　|　○　|　○　| ○ |

## なぜletやconstは追加されたのか？
varの改善をせずにconst、letを追加することでvarの問題を回避することができた。
var自体の動作を変えなかったのは今までvarで書かれたコードの動作が変わりアプリケーション自体に影響が出てしまうためで今まで通りの挙動を取るために後方互換性を持たせた。

## 変数名で使える名前のルール
変数名には使えるルールが存在する。
どのキーワードにおいても宣言できる変数に利用できる名前のルールは同じ、変数名や関数名の名前と言ったjsに出てくる識別子において同じルールとなる。

- 半角のアルファベット、_（アンダースコア）、$（ダラー）、数字を組み合わせた名前にする
- 変数名は数字から開始できない
- 予約語と被る名前は利用できない
- ひらがなやカタカナを利用することができるが環境によって扱いにくいので推奨はしない
- 変数・関数共に基本キャメルケース(camelCase)を用いる

変数として使える場合
```javascript!
let $; // OK: $が利用できる
let _title; // OK: _が利用できる
let jquery; // OK: 小文字のアルファベットが利用できる
let TITLE; // OK: 大文字のアルファベットが利用できる
let es2015; // OK: 数字は先頭以外なら利用できる
let 日本語の変数名; // OK: 一部の漢字や日本語も利用できる
```
変数として使えない時

変数名に数字を含めることは可能だが変数を数字から記載することはできない、これは変数と数値が区別できなるため。

また予約語を変数として扱うこともできない。
```javascript!
let 1st; // NG: 数字から始まっている
let 123; // NG: 数字のみで構成されている
let let; // NG: `let`は変数宣言のために予約されているので利用できない
let if; // NG: `if`はif文のために予約されているので利用できない
```

## constは定数ではない

constは再代入できない変数宣言であり、必ずしも定数とは限らない。

定数?
> 一度定義した名前（変数名）が常に同じ値を示すものです。


constは定数に近い変数宣言であるが、変更できないプリミティブな値で初期化すれば事実的に定数と呼ぶ
```javascript!
// TEN_NUMBERという変数に常に10という値を示す。
const TEN_NUMBER = 10
```
オブジェクトの場合だと...
```javascript=
// 'const'でオブジェクトを定義している。
const object = {
    key: "値"
};
// オブジェクトそのものは変更できてしまう
object.key = "新しい値";
```
jsでオブジェクトの定義は可能でconstでも定義は可能で変更も可能になる。
const宣言の特性として「再代入できない変数」を定義すると理解しておく

**まとめ**

- constは、再代入できない変数を宣言できる
- letは、再代入ができる変数を宣言できる
- varは、再代入ができる変数を宣言できるが、いくつかの問題が知られている
- 変数の名前（識別子）には利用できる名前のルールがある

varはほとんどすべてのケースでletやconstに置き換えが可能 
constは再代入できない変数を定義するキーワードです。再代入を禁止することで、ミスから発生するバグを減らすことができる。
このため変数を宣言する場合には、まずconstで定義できないかを検討し、できない場合はletを使う

**皆さんも何があれば！！！**

---
### 命名規則

**キャメルケース** ・・・`currentUserItem`
* 先頭の要素語(`current`)は小文字
* 先頭以外の要素語(`user`, `item`)の頭文字を大文字
* 使用例：JSの変数/関数名

<br/>

**パスカルケース**　・・・ `CurrentUserItem`
* 要素語(`current`, `user`, `item`)の頭文字を大文字
* 使用例：React, Vueのコンポーネント名

<br/>

**スネークケース** ・・・ `current_user_item`
* アンダースコアで要素語(`current`, `user`, `item`)を連結する
* 使用例：Rubyの変数名

<br/>

**ケバブケース** ・・・ `current-user-item`
* ハイフンで要素語(`current`, `user`, `item`)を連結する
* 使用例：HTMLのクラス名
