JavaScript Primerを読んで学んだこと（1/3）

#はじめに
この記事はJavaScriptの初心者向けに書かれています。
JavaScriptを体系的に学べるサイト「[JavaScript Primer](https://jsprimer.net/)」を読み、個人的に重要だと感じたことをまとめました。こちらはその第1回目（全3回）になります。
[第2回はこちら](https://qiita.com/thruaxle/items/03d27276c04d4fb0e5a2)
第3回は現在執筆中です。
JavaScriptを学習する際に参考にしていただければ幸いです。


#JavaScriptとは
ウェブサイトを操作したら表示が変わったり、ウェブサイトのサーバーと通信してデータを取得したりと、現在のウェブサイトには欠かせないプログラミング言語です。 

JavaScriptの大まかな特徴としては、以下が挙げられます。

1. オブジェクト指向言語である
2. 大文字と小文字を区別する
3. 文はセミコロンで区切られる
4. JavaScriptの仕様は毎年更新される



#変数と宣言
JavaScriptには、「これは変数です」という宣言をするキーワードとして ```const```、```let```、```var```の3つがあります。

###const

- 再代入できない変数の宣言と、その変数が参照する値（初期値）を定義する
- ```const```による変数宣言と初期値の定義は、必ず同時に行う

以下の例では、```bookTitle```という変数に```JavaScript Primer```という文字列を初期値として定義しています。
これ以降に変数```bookTitle```に別の値を代入しようとするとエラーになります。

```javascript
const bookTitle = "JavaScript Primer";
bookTitle = "hoge"; // => TypeError: invalid assignment to const 'bookTitle'
```

###let

- ```const```とは異なり、値の再代入が可能な変数を宣言できる
- 変数宣言と同時に初期値を定義する必要がなく、定義しなかった場合は自動的に```undefined```という値に設定される（undefinedは値が未定義ということを表す値）



```javascript
let bookTitle; // `bookTitle`は自動的に`undefined`という値になる
bookTitle = "JavaScript Primer"; //再代入が可能
```

###var

- 値の再代入が可能な変数を宣言できる

使い方は```let```とほとんど同じですが、以下のように同じ名前の変数を再定義できてしまうという問題があります。

```javascript
// letで変数"x"を定義する
let x;
// 同じ変数名の変数"x"を定義するとSyntaxErrorとなる
let x; // => SyntaxError: redeclaration of let x

// varで変数"x"を定義する
var x = 1;
// 同じ変数名の変数"x"を定義できる
var x = 2;
// 変数xは2となる
```

このように```var```には問題がありますが、ほとんどすべてのケースで```var```は```const```か```let```に置き換えが可能です。
そのため、これから書くコードに対して```var```を利用することは避けたほうがよいでしょう。



#リテラル
###ダブルクォートとシングルクォート
"（ダブルクォート）と'（シングルクォート）はまったく同じ意味となります。

###テンプレートリテラル
`（バッククォート）で囲んだ範囲を文字列とするリテラルです。
テンプレートリテラル内で${変数名}と書いた場合に、その変数の値を埋め込むことができます。

```javascript
const str = "文字列";
console.log(`これは${str}です`); // => "これは文字列です"
```


#演算子
###厳密等価演算子（===）
厳密等価演算子は、左右の2つのオペランドを比較します。同じ型で同じ値である場合に、trueを返します。
オペランドがどちらもオブジェクトであるときは、オブジェクトの参照が同じである場合に、trueを返します。

###等価演算子（==）
等価演算子は、2つのオペランドを比較します。同じデータ型のオペランドを比較する場合は、厳密等価演算子（===）と同じ結果になります。
しかし、等価演算子はオペランド同士が異なる型の値であった場合に、同じ型となるように暗黙的な型変換をしてから比較します。

```javascript
// 文字列を数値に変換してから比較
console.log(1 == "1"); // => true
// "01"を数値にすると`1`となる
console.log(1 == "01"); // => true
// 真偽値を数値に変換してから比較
console.log(0 == false); // => true
```
値を比較する際は常に厳密等価演算子（===）を使うことで、暗黙的な型変換をせずに値を比較できます。


###三項演算子（?と:）
三項演算子は条件式を評価した結果がtrueならば、?の後の式の評価結果を返します。条件式がfalseである場合は、:の後の式の評価結果を返します。

```javascript
条件式 ? Trueのとき処理する式 : Falseのとき処理する式;
```

以下の例では、```hoge === ○```の評価結果により"A" または "B" どちらかを返します。

```javascript
const hoge = 1;
const valueA = hoge === 1 ? "A" : "B";
console.log(valueA); // => "A"
const valueB = hoge === 2 ? "A" : "B";
console.log(valueB); // => "B"
```



#暗黙的な型変換
先ほども出てきた等価演算子（==）のように、JavaScriptではオペランド同士が同じ型となるように暗黙的な型変換をすることがあります。

次のコードでは、数値の1と文字列の"2"をプラス演算子で処理しています。プラス演算子（+）は、数値の加算と文字列の結合を両方実行できるように多重定義されています。そのため、数値の1を文字列の"1"へ暗黙的に変換してから、文字列結合します。

```javascript
1 + "2"; // => "12"
// 演算過程で次のように暗黙的な型変換が行われる
"1" + "2"; // => "12"
```

また、次のコードでは数値の1から文字列の"2"を減算しています。JavaScriptには文字列に対するマイナス演算子（-）の定義はないので、暗黙的な型変換が行われます。これにより、文字列の"2"を数値の2へ暗黙的に変換してから、減算します。

```javascript
1 - "2"; // => -1
// 演算過程で次のように暗黙的な型変換が行われる
1 - 2; // => -1
```
このように、暗黙的な型変換は意図しない結果になることが多いので、次に示す明示的な型変換を行い避けることが望ましいです。

#明示的な型変換
JavaScriptでは、以下のような関数を用いることで任意の値を様々な型に変換することができます。

```javascript
Boolean(0); // => false
String(null); // => "null"
Number("1"); // => 1
```

Boolean( )を使用した際に、どの値がtrueでどの値がfalseになるかは、次のルールによって決まります。

- falsyな値はfalseになる
- falsyでない値はtrueになる

falsyな値とは次の7種類の値のことを言います。

- false
- undefined
- null
- 0
- 0n
- ""（空文字列）
- NaN（"Not-a-Number"の略称で、数値ではないがNumber型の値を表現している）


#関数と宣言
###functionキーワード
JavaScriptでは、関数を定義するためにfunctionキーワードを使います。

```javascript
// 関数宣言
function 関数名(仮引数1, 仮引数2) {
    // 関数が呼び出されたときの処理
    // ...
    return 関数の返り値;
}
// 関数呼び出し
const 関数の結果 = 関数名(引数1, 引数2);
console.log(関数の結果); // => 関数の返り値
```

定義した関数の仮引数よりも呼び出し時の引数が少ない場合は、余った仮引数にはundefinedという値が代入されます。
逆に、関数の仮引数に対して引数の個数が多い場合、あふれた引数は単純に無視されます。

###関数式
関数式とは、関数を値として変数へ代入している式のことを言います。関数宣言は文でしたが、関数式では関数を値として扱っています。

```javascript
// 関数式
const 変数名 = function(仮引数) {
    // 関数を呼び出したときの処理
    // ...
    return 関数の返り値;
};
// 関数呼び出し
console.log(変数名(引数)); // => 関数の返り値
```
関数式ではfunctionキーワードの右辺に書く関数名は省略できます。
このような名前を持たない関数を匿名関数と呼びます。


###Arrow Function
関数式にはArrow Functionと呼ばれる書き方もあり、functionキーワードよりも短く書くことができます。 
矢印のような=>（イコールと大なり記号）を使い、匿名関数を定義する構文です。 

```javascript
// 関数宣言
// Arrow Functionを使った関数定義
const 変数名 = (仮引数) => {
    // 関数を呼び出したときの処理
    // ...
    return 関数の返す値;
};
// 関数呼び出し
console.log(変数名(引数)); // => 関数の返り値
```
また、Arrow Functionには省略記法があり、次の場合は更に短く書けます。

- 関数の仮引数が1つのときは( )を省略できる
- 関数の処理が1つの式である場合に、ブロック({ })とreturn文を省略できる
 - その式の評価結果をreturnの返り値とする

```javascript
// 仮引数の数と定義
const fnA = () => { /* 仮引数がないとき */ };
const fnB = (x) => { /* 仮引数が1つのみのとき */ };
const fnC = x => { /* 仮引数が1つのみのときは()を省略可能 */ };
const fnD = (x, y) => { /* 仮引数が複数のとき */ };
// 値の返し方
// 次の２つの定義は同じ意味となる
const mulA = x => { return x * x; }; // ブロックの中でreturn
const mulB = x => x * x;            // 1行のみの場合はreturnとブロックを省略できる
```

#オブジェクト
オブジェクトはプロパティ（キーと値が対になったもの）の集合です。
オブジェクトを作成するには、オブジェクトリテラル（{ }）を利用します。

```javascript
const obj = {
    // キー: 値
    key: "value"
};
```
###プロパティへのアクセス

オブジェクトのプロパティにアクセスする方法として、ドット記法（.）とブラケット記法（[ ]）があります。
それぞれの記法でプロパティ名を指定すると、その名前を持ったプロパティの値を参照できます。

```javascript
const obj = {
    key1: "value1"
    key2: "value2"
};
// ドット記法で参照
console.log(obj.key1); // => "value1"
// ブラケット記法で参照
console.log(obj["key2"]); // => "value2"
```
###プロパティの追加と削除
オブジェクトは、一度作成した後もその値自体を変更できるというミュータブル（mutable）の特性を持ちます。そのため、作成したオブジェクトに対して、後からプロパティを追加・削除することができます。

プロパティの追加方法は単純で、作成したいプロパティ名へ値を代入するだけです。そのとき、オブジェクトに指定したプロパティが存在しないなら、自動的にプロパティが作成されます。

```javascript
// 空のオブジェクト
const obj = {};
// `key`プロパティを追加して値を代入
obj.key = "value";
console.log(obj.key); // => "value"
```

また、オブジェクトのプロパティを削除するにはdelete演算子を利用します。削除したいプロパティをdelete演算子の右辺に指定して、プロパティを削除できます。

```javascript
const obj = {
    key1: "value1",
    key2: "value2"
};
// key1プロパティを削除
delete obj.key1;
// key1プロパティが削除されている
console.log(obj); // => { "key2": "value2" }
```

上記のコード例で、constで宣言したオブジェクトのプロパティを変更できていることに疑問を抱いた方がいるかもしれません。
JavaScriptのconstは値を固定するのではなく、変数への再代入を防ぐためのものです。そのため上記の例では、obj変数への再代入は防げますが、変数に代入された値であるオブジェクトの変更は防げません。

#続きについて
この記事はJavaScript Primerを読んで学んだことの第1回目（全3回）になります。
[第2回はこちら](https://qiita.com/thruaxle/items/03d27276c04d4fb0e5a2)
第3回についてもいずれ執筆予定です。