CSharp使いがJavaScriptへ乗り換えるためのクイックガイド

JavaScriptとC#は基本文法の雰囲気はそんなに遠くないです。
あくまでプログラミング言語としてみた場合、C#ちょっと書ける人がJavaScriptならではの理由でつまづくことって、初級中級レベルでは無さそうです。イラッとすることはたくさんあるかも。

JavaScriptからTypeScriptに入門しようとして苦労した人とそうでなかった人の両方を見たことがあるのですが
静的型付け言語(C#とかJavaとか)の経験者は割と入りやすかったようです。未経験者は結構苦労してました。
そこからの類推なのですがC#からJavaScriptは割と入門しやすい気がしてます。逆は苦労しそうです。。

:four_leaf_clover: お仕事でふだんC#使っているのですがこれからJavaScriptが必要になる雰囲気があるので初学者の後輩に向けて書きました。

:four_leaf_clover: 今Qiitaを見ているブラウザ上からコードのお試しができます。右クリック > 「要素の詳細を表示」で開発者用ツールを出してからコンソールタブへ移動したら、あとはこのページのサンプルコードをコピペするだけで動作確認できます(一部のぞく)


# 標準出力(Hello, World)
```js
console.log("Hello, World");
```

ブラウザ上で動かしている場合[^1]には、`window.alert()` とか `document.write()` を使ってみるのも面白いでしょう。
`console.log()` の結果をブラウザ上で確認する場合には、ブラウザ上で右クリックして開発者用ツールを表示する必要があります。

[^1]: ブラウザ上で動かさない場合: Node.jsとかがあります


# 変数宣言
```js
// どれでも動きますよ
let x = 42;
var y = 21 * 2;
const z = "Hello, World";
```

歴史的ないろんな経緯があって、`var` は今はあまり使いません。`let` または`const` を使います。
`let` は再代入が可能な変数です。`const` は再代入不可、つまり宣言した瞬間に値を入れないとダメです。
じゃあ全部`let` でいいじゃん、ということになるかもしれませんが`const` 使っておけば意図しないタイミングで値が書き換えられちゃうみたいなことを防げます。
使い分けていきましょう。[^2]

[^2]: 再代入はバグの温床になるからやめろという過激な方もいますのでプロジェクトの方針に従ってください

## 型について
JavaScriptには変数の型がありません。(よく勘違いされますが値の型はあります)

## 文字列定数
ダブルクォーテーションかシングルクォーテーションで囲った文字列は定数として扱われます。どちらも意味は同じ。
:four_leaf_clover: 通例混ぜません。プロジェクトごとに、どちらかに統一するのが普通です。

```js
if ("aaa" == 'aaa') console.log("yes"); // yes
```

### テンプレートリテラル

バッククォートで囲っても文字列です。このときその中に`${}`で囲った式は計算された後最終的に文字列になります。
C#の文字列補間式`$"Hello, {name}"`と同じです。
```js
console.log(`11 * 11 = ${11 * 11}`); // 11 * 11 = 121

const name = 'TomK';
console.log(`Hello, ${name}`); // Hello, TomK
```

## キャスト
変数の型がないのでキャストもありません。[^3]
数値と文字列の変換とかは`parse` 系の関数を使います。

[^3]: ちょっと自信ない。。変換はあるけどキャストはないよね？

```js
const n = Number.parseInt("123");
console.log(n + 123); // 246
```

# 制御文
## `for`, `if`, `else`

FizzBuzzで理解しよう
```js
for(let i = 0; i < 30; i++) {
  if (i % 15 == 0) console.log("FizzBuzz");
  else if (i % 3 == 0) console.log("Fizz");
  else if (i % 5 == 0) console.log("Buzz");
  else console.log(i);
}
```

雰囲気はC#と同じです。
`while` `switch` あたりも似てるので雰囲気で乗り切れるはず

# オブジェクト

```js
const obj = {
  a: "alpha",
  b: "blavo",
  c: "charlie"
}

console.log(obj.a); // ドット記法
console.log(obj['b']); // ブラケット記法
```

オブジェクトは連想配列(辞書Dictionaryとも)っぽい雰囲気のやつです。
C#ではオブジェクトは「`Dictionary`型とか`List`型とか色々型がある」みたいな認識あるかもしれませんがJavaScriptにはそんなものはありません。
オブジェクトはほぼ全部`Object`型です。[^4]

[^4]: [MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object#解説) より。ここでいう「ほぼ」の例外は`Date`とか`Function`とか`Error`とかを指すってことでいいのだろうか、と思いましたが深く調べていないです

オブジェクトは入れ子もいけます。
```js
const obj2 = {
  tokyo: {
    minato: "akasaka",
    shinjuku: "yoyogi"
  },
  kanagawa: {
    yokohama: "minatomirai",
    kawasaki: "saiwai"
  }
};

console.log(obj2.tokyo.minato); // akasaka
```

みて気づいた方もいるかもしれませんがこれってJSONと似てますよね。
それもそのはずでJSONはJavaScript由来です。
JSONドキュメントはJavaScriptのオブジェクトとして有効な書式です。

# 配列とforeach

C#わかれば雰囲気でいけます、、と思ったけど結構違うかも
```js
const arr = [1, 2, 3];
const zipCodes = [
  {"zipCode": "100-0001", "address": "東京都千代田区千代田"},
  {"zipCode": "100-0002", "address": "東京都千代田区皇居外苑"},
  {"zipCode": "100-0003", "address": "東京都千代田区一ツ橋"},
];

for(let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

for(const z of zipCodes) {
  console.log(`郵便番号${z.zipCode}の住所は${z.address}です。`);
}
```

型がゆるゆるなので配列の宣言の際に「何の」配列なのかを宣言する必要がないです。する術もありません
なので何でもつっこめてしまいます。こういうことはあんまりしない方がいいです
:four_leaf_clover: 馬鹿馬鹿しいと思うかもしれませんが結構よく見かけます。元々C#使ってた人からするとおおっ！？と思いますけど
```js
let numbers = [1, "2", {number: 3}, 4.05};
```

## 配列操作(LINQ的な)
```js
const zipCodes = [
  {"zipCode": "100-0001", "address": "東京都千代田区千代田"},
  {"zipCode": "100-0002", "address": "東京都千代田区皇居外苑"},
  {"zipCode": "100-0003", "address": "東京都千代田区一ツ橋"},
];

const searchResult = zipCodes
    .filter(zipCode => zipCode.address.includes("東京都"))
    .filter(zipCode => zipCode.zipCode.startsWith("100-"));

console.log(searchResult);
```

## 対応表

### 中間操作

|C#|JS|
|:--|:--|
|Select|map|
|SelectMany|flatMap|
|Where|filter|
|OrderBy|sort|
|Reverse|reverse|

### 終端操作

|C#|JS|
|:--|:--|
|First|[0]って書くことが多いけどat(0)もいけそう[^5]|
|Last|at(-1) [^5]|
|All|every|
|Contains|includes|
|Reduce|reduce|
|Any|some|
|ToList|(なし) JavaScriptの配列操作は配列を返すので、いちいち変換不要|

[^5]: [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at) より。使ったことありません

## 配列操作
配列に要素を足す、取り除く

```js
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.push(11); // 末尾に要素を追加する
console.log(arr.pop()); // 末尾から要素を取り出す
arr.splice(3, 0, 3.14); // 途中に要素を追加したり、途中の要素を変更したりする
```

# 関数
```js
function sum(a, b) {
  return a + b;
}

const result = sum(1, 2);
console.log(result); // 3
```

初歩的な関数はあんまり難しいことはないです
戻り値と引数に型がないことに注意。明示しなくていいし、裏を返せば明示できません。

## 関数/メソッドを書ける場所
C#ではメソッドを宣言できる場所は決まっていました。(クラスの中でメンバーとして宣言する)
JavaScriptでも同様で、処理フロー内には書きません。トップレベルか、クラスのメンバーとして宣言します。

## 関数の別の宣言の仕方


```js:このサンプルは上から順番に試した場合にはsum関数が重複してるのでうまく動かないかも
const sum = function(a, b) {
  return a + b;
}

const result = sum(1, 2);
console.log(result);
```

`function`の後に名前を入れるのではなく、無名で関数を作り、それを変数の中に突っ込むというやり方もできます
まあ似たようなものかと思うかもしれませんが、これが可能ということは __関数をオブジェクトとして扱うことができる__ という意味です。つまり・・

```js: このサンプルはaxiosらへんがインポートしてないしテキトウな書き方なのでうまく動きません
const errorLog = function(e) {
  console.log("エラーが起きました。内容: " + e);
}

const submit = function(text) {
  axios.POST("www.example.com", text); // 中身はてきとう
}

const process(mainProcess, arg, onError) {
  try {
    mainProcess(arg);
  } catch (err) {
    onError(err);
  }
};

process(submit, "hello world", errorLog);
```

みたいな書き方ができるということです。よく聞くコールバック関数を渡すとかいうのはこういう仕組みを使います。
:four_leaf_clover: まだ聞いたことなくても今後嫌というほど聞くはずです

あとアロー関数の書き方を使うこともできます
```js:このサンプルは上から順番に試した場合にはsum関数が重複してるのでうまく動かないかも
const sum = (a, b) => a + b;
sum(1, 2);

[1, 2, 3, 4, 5, 6, 7, 8, 9]
.map(x => x * x)
.forEach(x => console.log(x)); // 1から9までの数の2乗
```

# クラス

C#と同様普通にクラスを使えます
メンバ変数の宣言とコンストラクタの書式に注意
~~あとアクセサ(privateとかpublicとか)はありません~~ 最近追加されました。みんな使っているのかはわからないけど
```js
class MyClass {
  a;
  b;

  c() {
    return this.a * this.b;
  }

  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
}

const myCls = new MyClass(1, 2);
console.log(myCls.c()); // 2
```

# 比較, Truthy, Falsy
JavaScriptでは `==` ではなく `===` を使えとよく言われます。詳細はググってください。

# `null`, `undefined`
[JavaScriptには`null`の他に`undefined`とかいう謎な何かがあります。](https://qiita.com/TomK/items/37b100195aa7142868c8) 詳細はググってください。私もよくわかってないので
値が入っていない時によく見ますけど`null`との本質的な違いは本当によくわからんのや・・・

# 外部モジュール

## import
外部モジュールの読み込み
JavaScriptには大別して2系統の言語仕様があります[^6]。処理系で言うとブラウザとNode.jsです。仕様でいうとECMAScriptとCommonJSです。
とりあえずimport 文はECMAScriptの書き方です。

[^6]: この辺厳密なこと調べて書いていないので何か気づいた方がいたら教えてください

```js:このサンプルはインポート内容とかがテキトウなので動きません
import x from 'xxx';
import { a, b, c } from 'abc';
import x as a from 'xyzjs'; // xと名前がかぶるのでasで呼び方を変えている
```

## export
`import`文を使って外部モジュールとして読み込み可能にするための構文です。
C#でいうところの`public`みたいなものだと思ってください。

# `async`, `await` 
C#と同様。特にWebアプリを作る時とかは、サーバーとのやり取りを待つ必要があるため多用します。
C#ではasyncな関数は`Task` を返しますがJavaScriptでは`Promise` を返します。一緒です

:four_leaf_clover: 何を言っているんだという人は無理してついてこようとしなくていいです、非同期の基礎からゆっくりやりましょう

# フォームとのやり取り
入門レベルを超えて実践的な内容に入ってしまうので簡単に触れるだけにしておきます。
JavaScriptが活躍する重要な場面はもちろんWebブラウザであり、JavaScriptのコードはhtmlとセットで読み込まれることが多いです。
なのでJavaScriptコードをhtmlに埋め込んで、フォームから情報を受け取って処理を行って表示するまでの流れを見てみましょう

```html:このサンプルはHTMLなのでコンソールに貼り付けても動かないです
<html>
  <script>
    function printSum(){
      const a = document.getElementById("a").value;
      const b = document.getElementById("b").value;

      const sum = Number.parseInt(a) + Number.parseInt(b);

      document.getElementById("result").innerHTML = sum;
    }
  </script>

  <input id="a"></input>
  <input id="b"></input>
  <button onclick="printSum()">SUM</button>
  <span id="result"></span>
</html>
```

![無題23_20220618175838.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156941/ae046064-7d58-c00e-5928-3de51bc8f91e.png)


:four_leaf_clover: なるべく簡素化しつつこれまで扱った内容だけを使って説明するために、色々と「普通こういう書き方しないよね」みたいものが含まれているんですが
わかっている人は相手にしていないので無視しますね

ポイントになるのは
`document.getElementById()` を使って文書の中に埋め込まれている要素を取ってきていること
`button` 要素の`onclick` 属性で、クリック時のアクションを指定していること

ノリはこんな感じです。
実際には現代では`onclick` を使った書き方はしないみたいです。でもVue.jsの`@click` と書き方が酷似しているので、廃れたとはいえ考え方は悪くないと個人的には思います。
一方で`document.getElementById()` は結構書き方が長ったらしいですよね、この辺のめんどくささを解消してくれるのがVue.jsなどのフレームワークなわけです。これ以上はJavaScript自体の入門レベルは超えるのでここまで！

---

:four_leaf_clover: 余談。気づいたんですが初学者の人向けの、モダンなJavaScriptの体系的な無料の入門サイトってなくないですか？C#だと[未確認飛行C](https://ufcpp.net)さんとか超有名じゃないですか。MDNはちょっと難しいし。誰か作ってください