JavaScriptとC#は基本文法の雰囲気はそんなに遠くないです。
あくまでプログラミング言語としてみた場合、C#ちょっと書ける人がJavaScriptならではの理由でつまづくことって、初級中級レベルでは無さそうです。イラッとすることはたくさんあるかも。
JavaScriptからTypeScriptに入門しようとして苦労した人とそうでなかった人の両方を見たことがあるのですが
静的型付け言語(C#とかJavaとか)の経験者は割と入りやすかったようです。未経験者は結構苦労してました。
そこからの類推なのですがC#からJavaScriptは割と入門しやすい気がしてます。逆は苦労しそうです。。
お仕事でふだんC#使っているのですがこれからJavaScriptが必要になる雰囲気があるので初学者の後輩に向けて書きました。
今Qiitaを見ているブラウザ上からコードのお試しができます。右クリック > 「要素の詳細を表示」で開発者用ツールを出してからコンソールタブへ移動したら、あとはこのページのサンプルコードをコピペするだけで動作確認できます(一部のぞく)
標準出力(Hello, World)
console.log("Hello, World");
ブラウザ上で動かしている場合1には、window.alert()
とか document.write()
を使ってみるのも面白いでしょう。
console.log()
の結果をブラウザ上で確認する場合には、ブラウザ上で右クリックして開発者用ツールを表示する必要があります。
変数宣言
// どれでも動きますよ
let x = 42;
var y = 21 * 2;
const z = "Hello, World";
歴史的ないろんな経緯があって、var
は今はあまり使いません。let
またはconst
を使います。
let
は再代入が可能な変数です。const
は再代入不可、つまり宣言した瞬間に値を入れないとダメです。
じゃあ全部let
でいいじゃん、ということになるかもしれませんがconst
使っておけば意図しないタイミングで値が書き換えられちゃうみたいなことを防げます。
使い分けていきましょう。2
型について
JavaScriptには変数の型がありません。(よく勘違いされますが値の型はあります)
文字列定数
ダブルクォーテーションかシングルクォーテーションで囲った文字列は定数として扱われます。どちらも意味は同じ。
通例混ぜません。プロジェクトごとに、どちらかに統一するのが普通です。
if ("aaa" == 'aaa') console.log("yes"); // yes
テンプレートリテラル
バッククォートで囲っても文字列です。このときその中に${}
で囲った式は計算された後最終的に文字列になります。
C#の文字列補間式$"Hello, {name}"
と同じです。
console.log(`11 * 11 = ${11 * 11}`); // 11 * 11 = 121
const name = 'TomK';
console.log(`Hello, ${name}`); // Hello, TomK
キャスト
変数の型がないのでキャストもありません。3
数値と文字列の変換とかはparse
系の関数を使います。
const n = Number.parseInt("123");
console.log(n + 123); // 246
制御文
for
, if
, else
FizzBuzzで理解しよう
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
あたりも似てるので雰囲気で乗り切れるはず
オブジェクト
const obj = {
a: "alpha",
b: "blavo",
c: "charlie"
}
console.log(obj.a); // ドット記法
console.log(obj['b']); // ブラケット記法
オブジェクトは連想配列(辞書Dictionaryとも)っぽい雰囲気のやつです。
C#ではオブジェクトは「Dictionary
型とかList
型とか色々型がある」みたいな認識あるかもしれませんがJavaScriptにはそんなものはありません。
オブジェクトはほぼ全部Object
型です。4
オブジェクトは入れ子もいけます。
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#わかれば雰囲気でいけます、、と思ったけど結構違うかも
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}です。`);
}
型がゆるゆるなので配列の宣言の際に「何の」配列なのかを宣言する必要がないです。する術もありません
なので何でもつっこめてしまいます。こういうことはあんまりしない方がいいです
馬鹿馬鹿しいと思うかもしれませんが結構よく見かけます。元々C#使ってた人からするとおおっ!?と思いますけど
let numbers = [1, "2", {number: 3}, 4.05};
配列操作(LINQ的な)
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の配列操作は配列を返すので、いちいち変換不要 |
配列操作
配列に要素を足す、取り除く
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); // 途中に要素を追加したり、途中の要素を変更したりする
関数
function sum(a, b) {
return a + b;
}
const result = sum(1, 2);
console.log(result); // 3
初歩的な関数はあんまり難しいことはないです
戻り値と引数に型がないことに注意。明示しなくていいし、裏を返せば明示できません。
関数/メソッドを書ける場所
C#ではメソッドを宣言できる場所は決まっていました。(クラスの中でメンバーとして宣言する)
JavaScriptでも同様で、処理フロー内には書きません。トップレベルか、クラスのメンバーとして宣言します。
関数の別の宣言の仕方
const sum = function(a, b) {
return a + b;
}
const result = sum(1, 2);
console.log(result);
function
の後に名前を入れるのではなく、無名で関数を作り、それを変数の中に突っ込むというやり方もできます
まあ似たようなものかと思うかもしれませんが、これが可能ということは 関数をオブジェクトとして扱うことができる という意味です。つまり・・
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);
みたいな書き方ができるということです。よく聞くコールバック関数を渡すとかいうのはこういう仕組みを使います。
まだ聞いたことなくても今後嫌というほど聞くはずです
あとアロー関数の書き方を使うこともできます
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とか)はありません 最近追加されました。みんな使っているのかはわからないけど
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
とかいう謎な何かがあります。 詳細はググってください。私もよくわかってないので
値が入っていない時によく見ますけどnull
との本質的な違いは本当によくわからんのや・・・
外部モジュール
import
外部モジュールの読み込み
JavaScriptには大別して2系統の言語仕様があります6。処理系で言うとブラウザとNode.jsです。仕様でいうとECMAScriptとCommonJSです。
とりあえずimport 文はECMAScriptの書き方です。
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
を返します。一緒です
何を言っているんだという人は無理してついてこようとしなくていいです、非同期の基礎からゆっくりやりましょう
フォームとのやり取り
入門レベルを超えて実践的な内容に入ってしまうので簡単に触れるだけにしておきます。
JavaScriptが活躍する重要な場面はもちろんWebブラウザであり、JavaScriptのコードはhtmlとセットで読み込まれることが多いです。
なのでJavaScriptコードを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>
なるべく簡素化しつつこれまで扱った内容だけを使って説明するために、色々と「普通こういう書き方しないよね」みたいものが含まれているんですが
わかっている人は相手にしていないので無視しますね
ポイントになるのは
document.getElementById()
を使って文書の中に埋め込まれている要素を取ってきていること
button
要素のonclick
属性で、クリック時のアクションを指定していること
ノリはこんな感じです。
実際には現代ではonclick
を使った書き方はしないみたいです。でもVue.jsの@click
と書き方が酷似しているので、廃れたとはいえ考え方は悪くないと個人的には思います。
一方でdocument.getElementById()
は結構書き方が長ったらしいですよね、この辺のめんどくささを解消してくれるのがVue.jsなどのフレームワークなわけです。これ以上はJavaScript自体の入門レベルは超えるのでここまで!
余談。気づいたんですが初学者の人向けの、モダンなJavaScriptの体系的な無料の入門サイトってなくないですか?C#だと未確認飛行Cさんとか超有名じゃないですか。MDNはちょっと難しいし。誰か作ってください