【JavaScript】javascriptの基本

# javascript
JavascriptはWEBブラウザ（クライアント側）の中で動くプログラミング言語。
ユーザーのブラウザ上で作動し、ユーザーがサイト上で何か操作をするとそれに合わせてサイトの構造を（HTML）を変えることができる。
サーバー側でも使用することができる。

だが、Javascriptで直接HTMLを操作することはできないので、`DOM`という仕組みを用いる。

## DOM

プログラムでHTMLを自由に操作するための仕組み。
JavascriptはDOMを介してHTMLにアクセスすることができる。

ブラウザがwebページにアクセスしHTMLを解析すると、HTMLの内容を表すオブジェクトのツリー構造が構築される（`DOMツリー`）。

JavascriptではこのDOMツリーからHTMLの情報を取得して変更を加える。

[参考記事](https://qiita.com/KDE_SPACE/items/e21bb31dd4d9c162c4a6#dom%E3%81%A8%E3%81%AF)


## 変数(variable)
扱いたい数値や文字列、配列などのデータを格納し、名前をつけたもの。
### 変数の定義

```sample.js
// 変数 value を定義し、1を格納
var value = 1;
```
一度宣言した変数にはあとから違う値を格納することができる。
※`var`で宣言したときのみ再宣言・再代入が可能ということに注意。

```sample.js
var value = 1;
// 再代入
value = 2;
```

### 変数宣言
変数を宣言する際に使用するワード


|           |let|var|const|
|:---------:|:-:|:-:|:---:|
| 再宣言     | 不可能      | 可能       |不可能|
| 再代入     | 可能        | 可能      |不可能|
| スコープ    | ブロックスコープ| 関数スコープ|ブロックスコープ|
| 繰り返し構文 | 可能        | 可能      |不可能|


#### var
再宣言、再代入が可能。

```sample.js
var variable = '初期値';
variable = '再代入OK';
var variable = '再宣言OK';
```
#### let
再代入は可能だが、再宣言は不可。

```sample.js
let variable = '初期値';
variable = '再代入OK';
let variable = '再宣言NG';
```
#### const
再代入/再宣言が不可。

→　[参考記事：【JavaScript】let、const、varの違いと使い分け方法を徹底解説](https://techplay.jp/column/1619)

```sample.js
const variable = '初期値';
variable = '再代入NG';
const variable = '再宣言NG';
```

## 関数（function)
まとまった処理が入った箱のようなもの。何度も使い回しができる。
プログラムが大きくなると同じ処理を繰り返し使う場面が出てくるが、関数を使うことでスマートなプログラムを書くことができる。
変更が生じた場合も変更点が一箇所で済むというメリットがある。
関数は変数に代入したり、関数の引数として渡したり、返り値として関数を返すことができる。
関数はオブジェクトでもある。

### 関数の定義
```sample.js
// 関数 valueを定義
function value() {
// ここに処理をかく
}
```

**引数や返り値(return)を入れて**

```sample.js
// 関数 valueを定義し、引数 numberを渡す
function value(number) {
// ここに処理をかく
// numberを2乗した値を返す
  return number * number;
}
```

### 関数式（関数リテラル）
関数式（関数リテラル）という関数の書き方もある。
宣言する際に関数名を記述しなくてもいいので無名関数などとも呼ばれる。

```sample.js
// 変数をvalueを定義し、その中に関数を代入
var value = function() {
// ここに処理をかく
}
```
上記のコードでは定義する際に関数名を記述しないでそのまま変数に関数を代入している。

### アロー関数
アロー関数は```function()```の代替文。```=>```を用いて、通常の関数よりも短く記述することができる。

```sample.js
// 通常の関数
var value = function(number) {
// ここに処理をかく
}

//アロー関数
var value = (number) => {
// ここに処理をかく
}
```
処理が1行の場合は```{ }```で囲まなくてOK

```sample.js
var value = (number) => ここに処理をかく ;
```
引数がない場合

```sample.js
// 引数がない場合は()内は空
var value = () => ここに処理をかく ;
```
### コールバック関数
関数の引数として渡される関数。特定のタイミングで処理を実行させることができ、ある処理が終わった後に関数を実行させる時などに使用する。

```sample.js
// A関数（コールバックとして実行される関数）
function hello() {
  console.log('hello');
}

// B関数（コールバックを実行する関数）
function execute(callback) {
  callback();
}

// hello関数を引数としてexecute関数を実行
execute(hello);
```
🌟 処理の流れ
① execute関数を実行。引数としてhello関数を渡す。
② execute関数が呼ばれると引数のcallbackにhello関数が入る。
③ execute関数の中でcallbackを実行（hello関数を実行）
④ console.logでhelloを出力


## 引数(parameter)
ある処理の結果を作るために渡される変動する値。
引数は複数指定することも可能。その場合はカンマで区切る。

```sample.js
function value(引数1, 引数2, 引数3) {
処理
}
```

## 返り値（return）とは
関数内でreturn文を呼び出すと関数の実行が停止する。
返り値に値が指定されていればその値を関数の呼び出している場所で返す。
特に式や値が指定されていなければ```undefind```を返す。

```sample.js
// 指定がないのでundefindを返す
return;
```

## プロパティ
特定の情報（値）に名前をつけたもの。

```sample.js
// プロパティ名:値
number: 10
string: 'apple'
array: ['apple','orange','banana']
```
## メソッド
オブジェクトのプロパティに代入された関数のこと。
あるオブジェクトのプロパティに関数を定義した場合、関数とは呼ばずメソッドと呼ぶ。

```sample.js
{
  name:'apple',
  price:100,
  // halfPriceがメソッド
  halfPrice: function() {
    return price / 2
  } 
}
```

## オブジェクト
プロパティやメソッドの集まり。
集まりに名前（プロパティ名）をつけて管理できるもの。

```sample.js
// { プロパティ名:値 , プロパティ名:値 }
{ name:'apple' , price:100 }

// オブジェクトの中に配列を記述することも可能
{ name:'apple' , price: [100,200,300] }
```

※配列や関数も一種のオブジェクト

## コンストラクタ
インスタンス（複製）を作成・初期化するための関数
ES6以前にはクラスがなかったのでこのコンストラクタを使って擬似的なクラスを作成していた

### 初期化
ここでいう初期化とは最初の状態を整えるということ。使い始める前に初期値を設定することを初期化という。

↓下記コードはPersonというコンストラクタを定義している
```sample.js
// コンストラクタを定義
function Person(name, age) {
  this.name = name;
  this.age = age;
}
// インスタンス化（複製を作成）してpersonという変数にインスタンス（複製）を代入
const person = new Person('太郎', 20);

console.log(person.name); // 太郎
console.log(person.age);  // 20
```

## クラス
クラスとはオブジェクトのフォーマット・設計図みたいなもの。
このクラス（フォーマット）を使えば、共通のプロパティやメソッドを保持したオブジェクトを必要に応じて生成することができ、同じ性質を持つ異なるオブジェクトを作成することができる。
例えば、ログインが必要なアプリケーションであればユーザーに関するデータ（オブジェクト）を用いる。
これらのデータを生成するためにオブジェクトの```クラス```（フォーマット）を作成しておくことで効率的にオブジェクトを生成することができる。

[クラスをクッキーに例えたこの記事がわかりやすい](https://xtech.nikkei.com/atcl/nxt/column/18/02780/032100003/)

### クラスを宣言
`class`を使用して宣言をし、そのクラス内にプロパティやメソッドを定義していく
クラス名は基本的に大文字から始めるようにする

```sample.js
// Userクラスを生成
class User {
}
```

## インスタンス
クラスから作成されたオブジェクトのことを```インスタンス```と呼ぶ。
クラスという名のオブジェクトで定義したデータや機能を持ったクラスの複製。
インスタンスはクラス（フォーマット）をもとに生成される。

※ES6以前はクラスが使えなかったため、クラスではなくコンストラクタからインスタンスを生成していた。（現在はjavascriptでクラスを使用することができる）

### インスタンス化
クラスからオブジェクトを生成することをインスタンス化（複製を作成）という。

### インスタンスを生成
下記コードのように```new```を用いてクラスを呼び出すことでインスタンスが生成される。

```sample.js
// Userクラスを生成
class User {
}
// Userクラスからインスタンスを生成して変数userに代入(変数userがインスタンスとしての役割をもつ)
var user = new User();
```

### なぜインスタンスを生成するのか？
例えば、AとBというプログラムがあったとして、両方のプログラムが全く同じオブジェクト（クラス）に対して読み書きをしてしまうと、お互いに干渉してしまってプログラムが動作しなくなってしまう。
なので、オブジェクト（クラス）をAとBそれぞれでコピー（インスタンス）して読み書きすることで干渉することなくプログラムを読み書きすることができる。


### コンストラクタメソッド
`class`内で使用されるインスタンスを生成する際に呼び出される特別なメソッド。初期化も行う。
今まで擬似的にクラスを生成する際に使用していたコンストラクタをクラスに組み込んだような形。
クラス内でインスタンスを作成し、初期化している。


## スプレッド構文
配列やオブジェクトを展開する構文。ドットを`...`と3つつけるとスプレッド構文になる。
スプレッド構文で展開すると`[ ]`や`{ }`が外れる。配列やオブジェクトとしてまとまっていた要素をバラバラにするので`スプレッド`。

```sample.js
const number = [ 1, 2, 3 ]

console.log(number); // [ 1, 2, 3 ]
console.log(...number); // 1 2 3
```

### 使用方法
#### 配列をマージ

```sample.js
const a = [ 1, 2, 3 ]
// 変数aに新しい値を追加したものを変数bとする
const b = [...a, 4, 5, 6 ]
console.log(b); // [ 1, 2, 3, 4, 5, 6 ]
```
#### 配列をコピー（シャローコピー）

```sample.js
const a = [ 1, 2, 3 ]
// スプレッド構文を使って変数aをコピー
let c = [...a]
// 変数cに値を追加
c.push(4)
// 参照先の変数aを変えず、変数cにだけ値を追加することができた
console.log(a); // [ 1, 2, 3 ]
console.log(c); // [ 1, 2, 3, 4 ]
```

##### なぜコピーするのか？
破壊的な変更を行った場合、参照先の値も変更されてしまうため。
コピーすることで参照先のオブジェクト(配列)とは別物のオブジェクト(配列)を生成することができ、参照先の値に影響を及ぼすこともない。
※あくまでも1階層だけのコピーなので、ネストしている値はコピーされないので注意。

↓ コピーしないで配列の値を変更してみる

```sample.js
const a = [ 1, 2, 3 ]
// コピーはせず、新たな変数cにaを代入
let c = a
// 変数cに値を追加
c.push(4)
// 変数a(元の配列)にも値が追加されてしまう
// ここでわかるのは、あくまでも変数cは変数aを参照しているだけということ
console.log(a ,c); // [ 1, 2, 3, 4 ] , [ 1, 2, 3, 4 ]
```

## 破壊的メソッドと非破壊的メソッド

配列オブジェクトには破壊的メソッドと非破壊的メソッドがある。
**破壊的メソッド**
元の配列そのものを直接操作（破壊）して変更した配列、または変更箇所を返すメソッド。
**非破壊的メソッド**
元の配列のコピーを作成してから変更し、そのコピーした配列を返すメソッド。