JavaScript基礎文法

#１．はじめに
この記事では、プログラミング経験者でJavaScrptは未経験な方向けの記事です。代入や宣言などといった基礎知識、実行環境の準備等は省略します。また、ここで紹介するものは実行環境によっては動作しないものも含まれます。予めご了承ください。
例えば、IE11(Internet Explorer 11)ではほとんど動作しません。[ECMAScript Compatibility Table](http://kangax.github.io/compat-table/es6/)で動作可能か確認するなどしてください。
詳しく知りたい方は、本文中で紹介する記事や最下部の[参考文献](https://qiita.com/yukuduri/items/cff4a1f9c85114600425#%EF%BC%91%EF%BC%91%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE)等を参照してください。

#２．とりあえずハロワ
この記事では、C言語の`printf`の代わりに`console.log`を使うことにします。

```javascript:HelloWorld.js
console.log('Hello, World!');
```

実行結果：

```
Hello, World!
```

#３．宣言
##3.1 基本的には`const`、ときどき`let`
変数宣言には基本的に`const`を用います。ただし、後ほど再代入する必要があれば、`let`を用います。C言語の`int x`のような型宣言は不要です。

```javascript:ValDec.js
const x = 10;
let y = 0;

console.log('x = ' + x);
console.log('y = ' + y);

y += x;
console.log('y += x');

console.log('x = ' + x);
console.log('y = ' + y);
```

実行結果：

```
x = 10
y = 0
y += x
x = 10
y = 10
```

##3.2 変数宣言 - 補足
3.1では、変数`y`を初期化していますが、初期化せずに、また並べて複数宣言することも出来ます。

```javascript
let x, y;
```

ただし、`const`で宣言するときは、初期化が必要です。

```javascript
const a, b;            // -> error
const a = 10, b = 5;   // -> OK 
```

##3.3 変数以外の宣言
関数やクラスなど、変数以外の宣言でも、二重定義による混同を防ぐため、`const`を用います。
`const`宣言は再代入（=アドレス変更）を制限するものなので、[配列自体を再代入するのは出来ませんが、配列への値の追加や書き換えはできるようです](https://qiita.com/NoobieGull/items/11d8c2bdcd82a01e8146)。
これらについては、これより下の項で少し詳しく説明します。

#４．文字列の結合
さて先程、`console.log('x = ' + x);`と、ナチュラルに文字列を結合していました。
文字列の結合は以下のように`+演算子`で結合できます。（文字列は、シングルクォート`'`またはダブルクォート`"`で括りますが、できるだけ`'`を使いましょう。例えばHTMLの`onclick`で関数呼び出し時など正常に動作しません。.jsファイルの中などJavaScriptしか記入しないような場所なら問題ないですが、統一しておいたほうがいいかと思います。）

```javascript:String.js
// 文字列同士の結合
console.log('ワレワレは' + '宇宙人ダ');

// 変数同士の結合
const str1 = '我々は', str2 = '宇宙', str3 = '人だ';
console.log(str1 + str2 + str3);

// 文字列と変数を混ぜて結合
const str4 = '日本';
console.log('わたしたちは' + str4 + '人だ');
```
実行結果：

```
ワレワレは宇宙人ダ
我々は宇宙人だ
わたしたちは日本人だ
```
他に、`${}`を用いた結合もあるようですが、ここではわかりやすさを重視するため省略します。
（Rubyでいう`#{}`みたいなものだけどJavaとかと同じ書き方をしたほうがわかりやすい……よね？）


#５．配列
##5.1 宣言
初期化する場合は、以下のように宣言します。

```javascript
const array1 = [1, 3, 5, 7, 9];
```
初期化しないのなら次のようにします。

```javascript
const array2 = [];
```
ちなみに、以下のような記述も出来ます。

```javascript
const array1 = new Array(1, 3, 5, 7, 9);
const array2 = new Array();
```
が、基本的には`[]`を使うのがいいでしょう。具体的な違いについては[new Array()と[]の違い - Qiita](https://qiita.com/Hiraku/items/d74690088dfa368875c9)を参照してください。
##5.2 値の追加や参照など
以下のような記述で追加や参照などを行います。ここに書いた以外のメソッドは、[配列 (Array) | JavaScript 日本語リファレンス | js STUDIO](http://js.studio-kingdom.com/javascript/array/)等を参照してください。

```javascript:Array.js
// 宣言
const array = [1, 3];

// 参照
console.log('array[0] = ' + array[0]);
console.log('array[1] = ' + array[1]);

// 長さの取得
console.log('array.length = ' + array.length);

// 要素の（末尾への）追加
console.log(array.push(5));    // 追加後の配列の長さを返す
console.log('array[0] = ' + array[0]);
console.log('array[1] = ' + array[1]);
console.log('array[2] = ' + array[2]);
console.log('array.length = ' + array.length);

// （末尾の）要素の削除
console.log(array.pop());    // 削除した値を返す
console.log('array[0] = ' + array[0]);
console.log('array[1] = ' + array[1]);
console.log('array.length = ' + array.length);
```
実行結果：

```
array[0] = 1
array[1] = 3
array.length = 2
3
array[0] = 1
array[1] = 3
array[2] = 5
array.length = 3
5
array[0] = 1
array[1] = 3
array.length = 2
```

`push`メソッドでは、

```javascript
const array = [];
array.push(1, 3, 5, 7, 9);
```
のように、複数の値を追加することも出来ます。

#６．関数
##6.1 関数の定義
関数の定義は、以下のように`アロー関数`を用います。

```javascript:FuncDec.js
const print = (text) => {
  console.log(text);
}

print('そんな装備で大丈夫か？');
print('大丈夫だ、問題ない');
```
実行結果：

```
そんな装備で大丈夫か？
大丈夫だ、問題ない
```

##6.2 `const`をなぜ用いるか
`const`で宣言することで、関数の再定義による過ちを防ぐことが出来ます。

```javascript
const print = (text) => {
  console.log(text);
}

print('ゆっくりしていってね！！！');

print = (text) => {
  document.write(text);
}

print('ゆっくりボイスとは、AquesTalkという音声合成エンジンの音声である。');
```

なんてことをしようもんなら勿論エラーを吐きます。
しかし、`let`で宣言されていれば、

```javascript
let print = (text) => {
  console.log(text);
}

print('斬れぬものなど、あんまり無い!');

print = (text) => {
  document.write(text);
}

print('斬れぬものなど、殆ど無い！');
```
なんてことが出来てしまい、
`斬れぬものなど、あんまり無い!`はコンソールに表示されるものの、
`斬れぬものなど、殆ど無い！`はコンソールには表示されない。。。
なんてことが起きてしまうのです。

##6.3 関数？メソッド？
JavaScriptには「関数」と「メソッド」の２つの言葉が存在します。オブジェクト内の「関数」をメソッドとも呼ぶ、ということらしいです。
詳しくは→[JavaScript - 関数とメソッドの違い。なぜ言い方を変えるのでしょうか？｜teratail](https://teratail.com/questions/59819)

##6.4 追記：返り値（戻り値）について
このページは自分で読み返してよく使っているのですが、見てたら返り値についての記載がなかった。
`return`文を使って返り値を定義できます。

```javascript:FuncDec2.js
const print = (text) => {
  console.log(text);
  return text;
}
```
とりあえず、引数をそのまま投げ返す無意味な関数を例として載せておきます。基本的に他の言語とほぼ変わらないと思いますので詳細は省略するので困ったときはその度にご自身で調べてください。


#７．分岐
以下に例を示しますが、他言語とあまり変わらないので詳細については省略します。詳しい仕様は各自でググるなどしてください。
##7.1 `if`文
`if`文は、以下のように書きます。比較演算子については、ここでは省略します。

```javascript:If.js
const a = 10, b = 0, c = -10;

// if文
if (a > b){
  console.log('aはbより大きい');
}

// if-else文
if (c <= b){
  console.log('cはb以下');
}else{
  console.log('cはbより大きい');
}

// if-elseif文
if (c > 0){
  console.log('cは0より大きい');
}else if(c < 0){
  console.log('cは0より小さい');
}else{
  console.log('cは0です');
}
```

実行結果：

```
aはbより大きい
cはb以下
cは0より小さい
```

##7.2 `switch`文
`switch`文は以下のように書きます。引数を２つ渡せたりしますが、ここでは省略します。

```javascript:Switch.js
const x = 2;
switch(x){
  case 1:
  case 2:
    console.log('case 1 or 2');
  case 3:
    console.log('breakしないとここも通る');
    break;
  default:
    console.log('どのcaseにもあてはまらないとき');
}
```
実行結果：

```
case 1 or 2
breakしないとここも通る
```

また、上記で`x`が文字列のとき、

```javascript
const x = '猫派';
switch(x){
  case '猫派':
    console.log('xは猫派');
    break;
  case '犬派':
    console.log('xは犬派');
    break;
  default:
    console.log('xは邪道派');
}
```
のように`'`で囲うのをお忘れなく。

#８．繰り返し
ここではひとまず、`for`文、`forEach`メソッド、`while`文を簡単に例示します。
前項と同じく、詳細はググってくださいね。

##8.1 `for`文
以下に示すのは、配列の中身をすべて書き出すサンプルプログラムです。

```javascript:ArrayFor.js
const array = [1, 3, 5, 7, 9];
for (let i = 0; i < array.length; i++){
  console.log('array[' + i + '] = ' + array[i]);
}
```
実行結果：

```
array[0] = 1
array[1] = 3
array[2] = 5
array[3] = 7
array[4] = 9
```
##8.2 `forEach`メソッド
8.1のように配列の中身をすべて書き出すのであれば、`forEach`メソッドを用いて以下のようにも書けます。

```javascript:ArrayForEach.js
const array = [1, 3, 5, 7, 9];
array.forEach((value, i) => {
  console.log('array[' + i + '] = ' +value);
});
```
実行結果：

```
array[0] = 1
array[1] = 3
array[2] = 5
array[3] = 7
array[4] = 9
```
`(value,i)`は、それぞれ8.1の`array[i]`、`i`に相当します。
詳しいことは[だいたいの繰り返しは配列のforEach()でいける。（配列とかおれおれAdvent Calendar2018 – 17日目）](https://ginpen.com/2018/12/17/array-foreach/) や [Array.prototype.forEach() – JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) を参照してください。

また、関数を呼び出すことも出来ます。例えば、こんな事もできます。~~やばいですね！（byペコリーヌ）~~

```javascript:ArrayForEach2.js
const array = [1, 3, 5, 7, 9];
const print = (text) => {
  console.log(text);
}
array.forEach(print);
```
実行結果：

```
1
3
5
7
9
```

ただし、`forEach`メソッド以外にもいろいろなメソッドがありますので、状況に応じて使い分けてくださいね。
→[JavaScript で forEach を使うのは最終手段 - Qiita](https://qiita.com/diescake/items/70d9b0cbd4e3d5cc6fce)

##8.3 `while`文
以下のように書くことで、無限ループを実行します。

```javascript
while(true){
  console.log('止まるんじゃねえぞ...');
}
```

まあ、あとは他言語とほぼ同じなため省略しますね。
##8.4 そのほかの繰り返し
再帰を使っての繰り返しというのもできるみたいですが、~~再帰が苦手なので~~ ここでは省略しますね。
ほかにも`for ... of`があったりjQueryには`each`があったりとか・・・。

#９．クラス
筆者自身、オブジェクト指向な人間なもので。クラス使いたい。
最近のJavaScriptでは、`class`宣言ができるみたいです。やってみましょう。
（※一部環境では動作しませんのでご注意ください。[かつてはclass宣言ではなくprototype宣言してたりするらしい](https://togetter.com/li/1338234)ですが省略）

```javascript
class Human {
  constructor(name){
    this.name = name;
  }
}
```
このように、クラスのメンバは`constructor`メソッドの中で`this.`をつけて宣言します。
メソッドの定義ではアロー関数を使う必要はありません。やってみましょう。

```javascript:HumanClass.js
// Humanクラスの定義
class Human {
  constructor(name){
    this.name = name;
  }
  printName(){
    console.log(this.name);
  }
}

// Humanクラスのtaroを生成
const taro = new Human('Tanaka Taro');

// printNameメソッドの実行
taro.printName();
```
実行結果：

```
Tanaka Taro
```

`extends`を使うとクラス拡張もできます。先程の`Human`クラスを拡張してみましょう。

```javascript
class Student extends Human{
  constructor(name, number){
    super(name);
    this.number = number;
  }
}
```
`super`メソッドで親クラスの`constructor`メソッドを呼び出します。親クラスで定義済みのメソッドは子クラスにも継承されます。

```javascript:StudentClass.js
// Humanクラスの定義
class Human {
  constructor(name){
    this.name = name;
  }
  printName(){
    console.log(this.name);
  }
}

// Humanクラスの拡張
class Student extends Human{
  constructor(name, number){
    super(name);
    this.number = number;
  }
  printNumber(){
    console.log(this.number);
  }
}

// Studentクラスのhanako生成
const hanako = new Student('Sato Hanako', 127654);

// 親クラスのメソッド呼び出し
hanako.printName();

// 新たに作ったメソッドの呼び出し
hanako.printNumber();
```
実行結果：

```
Sato Hanako
127654
```

その他、細かいところは[JavaScriptのclass - Qiita](https://qiita.com/jooex/items/981824f9fb494b448a08)などを参照してください。

#１０．そのほか、いろいろ
ほかにも他言語でのハッシュに相当する連想配列があったりしますが例によって省略して、最後にletのスコープあたりを軽く。
8.1で、

```javascript
for (let i = 0; i < array.length; i++){
  console.log('array[' + i + '] = ' + array[i]);
}
```
と書きました。

```javascript
let i;
for (i = 0; i < array.length; i++){
  console.log('array[' + i + '] = ' + array[i]);
}
```
としていないのは、こうしてしまうと`for`文の終了後にも`i`が参照できてしまうためで、
例えば`for`文の後に`console.log(i);`と書くと`i`の5という値が出力できてしまいます。（前者だとエラーを吐きます）
`let`はブロックスコープで、宣言されたブロックの中でしか参照できません。
ですから、前者だと`for`文の中でしか参照できませんが、
後者だと`for`文の外で宣言されているため、外でも参照できてしまうのです。
ちなみにJavaScriptには`var`宣言がありますが、

```javascript
const array = [1, 3, 5, 7, 9];
for (var i = 0; i < array.length; i++){
  console.log('array[' + i + '] = ' + array[i]);
}

console.log(i);
```
などとしてしまうと`i`が参照できてしまいます。そういうのもあって、最近のJavaScriptでは`const`か`let`での宣言を推奨されてたり。
[未だシェア率の高いIE11でもconstとletは動作しますし](http://kangax.github.io/compat-table/es6/)ね。

#１１．参考文献
この記事は、以下のwebページを参考に作成さていただきました。ありがとうございました。
[イマドキのJavaScriptの書き方2018 - Qiita](https://qiita.com/shibukawa/items/19ab5c381bbb2e09d0d9)
[JavaScriptの定数(const)は「変更できない」わけではない。 - Qiita](https://qiita.com/NoobieGull/items/11d8c2bdcd82a01e8146)
[new Array()と[]の違い - Qiita](https://qiita.com/Hiraku/items/d74690088dfa368875c9)
[配列 (Array) | JavaScript 日本語リファレンス | js STUDIO](http://js.studio-kingdom.com/javascript/array/)
[JavaScript - 関数とメソッドの違い。なぜ言い方を変えるのでしょうか？｜teratail](https://teratail.com/questions/59819)
[だいたいの繰り返しは配列のforEach()でいける。（配列とかおれおれAdvent Calendar2018 – 17日目）](https://ginpen.com/2018/12/17/array-foreach/)
[Array.prototype.forEach() – JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
[JavaScript で forEach を使うのは最終手段 - Qiita](https://qiita.com/diescake/items/70d9b0cbd4e3d5cc6fce)
[このコードの書き方は年代もの!? 新しいJavaScriptの書き方をおさえよう - SaCSS](https://togetter.com/li/1338234)
[JavaScriptのclass - Qiita](https://qiita.com/jooex/items/981824f9fb494b448a08)
[ECMAScript Compatibility Table](http://kangax.github.io/compat-table/es6/)

#１２．さいごに
言い回しなどに不安のある箇所は調べて参考文献として掲載していますが、もし間違った点などございましたらコメントください。
初めてQiitaの記事を作成したのもあって、読みにくいところもあったかもしれませんが、ここまで読んでくださりありがとうございました。

追記：この記事の内容には賛否両論な内容も含まれています。固定概念に囚われず、賛成意見・反対意見どちらも聞き入れたうえで自分の考えを形成してくださいね (*^^*);